1

我正在使用 GHC 泛型。我的用例与 wiki 中的示例几乎相同,只是我正在编码和解码基因序列。

这一切都很好,直到我决定保留我已经阅读的内容列表,以便在出现错误时向用户报告。这意味着我需要为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))
4

1 回答 1

2

哦!我应该使用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
于 2015-07-20T14:23:14.883 回答