Добавление ограничения Show при использовании GHC.Generics

Я использую GHC Generics. Мой вариант использования практически идентичен примеру в вики, за исключением того, что я кодирую и декодирую последовательности генов.

Все это работало нормально, пока я не решил сохранить список того, что уже прочитал, чтобы я мог сообщить об этом пользователю в случае ошибки. Это означает, что мне нужно добавить Show ограничение по умолчанию get реализация. Проблема в том, что я не могу понять, как написать ограничение. Увидеть -- HELP!!! комментарий в коде ниже.

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE TypeOperators #-}

import Control.Monad.State.Lazy (StateT)
import qualified Control.Monad.State.Lazy as S (put, get, gets)
import Data.Functor.Identity (Identity)
import Data.Word (Word8, Word16)
import GHC.Generics

type Sequence = [Word8]

type Writer = StateT Sequence Identity

type Reader = StateT (Sequence, Int, [String]) Identity

class Genetic g where
  -- | Writes a gene to a sequence.
  put :: g -> Writer ()

  default put :: (Generic g, GGenetic (Rep g)) => g -> Writer ()
  put = gput . from

  -- | Reads the next gene in a sequence.
  get :: Reader (Either [String] g)

  default get :: (Generic g, GGenetic (Rep g), Show (Rep g x???)) -- HELP!!!
    => Reader (Either [String] g)
  get = do
    (_, start, _) <- S.get
    a <- gget
    (xs, stop, trace) <- S.get
    let msg = show start ++ ':' : show stop ++ ' ' : show a
    S.put (xs, stop, msg:trace)
    return $ fmap to a

class GGenetic f where
  gput :: f a -> Writer ()
  gget :: Reader (Either [String] (f a))

1 ответ

Решение

D'о! Я должен был использовать show (fmap to a) вместо show aЗатем все, что мне нужно было добавить Show g как ограничение.. Это простое изменение прекрасно компилируется:

  default get :: (Generic g, GGenetic (Rep g), Show g)
                => Reader (Either [String] g)
  get = do
    (_, start, _) <- S.get
    a <- gget
    (xs, stop, trace) <- S.get
    let result = fmap to a
    let msg = show start ++ ':' : show stop ++ ' ' : show result
    S.put (xs, stop, msg:trace)
    return result
Другие вопросы по тегам