我只是在Chris Done的ADT中使用默认示例gist available here,但遇到了一个问题:我的ADT(具有由更高种类类型的族定义的字段)不适用于派生的show实例。 GHC告诉我我需要派生一个Type Family的Show实例,但是我不确定该怎么做。到目前为止,这是我所拥有的,任何评论都将有所帮助。
在下面的示例中(使用ghc 8.8.1),目标是为Show
定义ShowMe
的实例,如果可能的话,使用派生。
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE PartialTypeSignatures #-}
{-# LANGUAGE ConstraintKinds #-}
data Tag = A | B deriving (Show)
type family TF (p :: Tag) a where
TF 'A a = ()
TF 'B a = a
data ShowMe p = ShowMe
{ a :: !(TF p String)
, b :: String
}
main = connect showMeDefaults { a = "some string" }
where
connect :: ShowMe B -> IO ()
connect _ = pure ()
showMeDefaults :: ShowMe A
showMeDefaults = ShowMe { a = (), b = "asdf" }
-- This works to define Show
{-
instance Show (ShowMe p) where
show _ = "hello"
-}
-- This instance is the line that causes an error
deriving instance Show (ShowMe p)
随后,我从GHC收到了一个我不熟悉的错误:
show_tf.hs:35:1: error:
• No instance for (Show (TF p String))
arising from a use of ‘showsPrec’
• In the first argument of ‘(.)’, namely ‘(showsPrec 0 b1)’
In the second argument of ‘(.)’, namely
‘((.)
(showsPrec 0 b1)
((.)
GHC.Show.showCommaSpace
((.)
(showString "b = ") ((.) (showsPrec 0 b2) (showString "}")))))’
In the second argument of ‘(.)’, namely
‘((.)
(showString "a = ")
((.)
(showsPrec 0 b1)
((.)
GHC.Show.showCommaSpace
((.)
(showString "b = ") ((.) (showsPrec 0 b2) (showString "}"))))))’
When typechecking the code for ‘showsPrec’
in a derived instance for ‘Show (ShowMe p)’:
To see the code I am typechecking, use -ddump-deriv
|
35 | deriving instance Show (ShowMe p)
如果我们使用ghc -ddump-deriv
重新编译,将返回以下内容:
[1 of 1] Compiling Main ( show_tf.hs, show_tf.o )
==================== Derived instances ====================
Derived class instances:
instance GHC.Show.Show Main.Tag where
GHC.Show.showsPrec _ Main.A = GHC.Show.showString "A"
GHC.Show.showsPrec _ Main.B = GHC.Show.showString "B"
Derived type family instances:
==================== Filling in method body ====================
GHC.Show.Show [Main.Tag]
GHC.Show.show = GHC.Show.$dmshow @(Main.Tag)
==================== Filling in method body ====================
GHC.Show.Show [Main.Tag]
GHC.Show.showList = GHC.Show.$dmshowList @(Main.Tag)
Linking show_tf ...
从概念上讲,我认为我应该能够为TF
派生一个Show实例,但是当我这样做时,我得到以下信息:
show_tf.hs:36:31: error:
• Illegal type synonym family application ‘TF 'A a’ in instance:
Show (TF 'A a)
• In the stand-alone deriving instance for
‘(Show a) => Show (TF 'A a)’
|
36 | deriving instance (Show a) => Show (TF 'A a)
如果我只是尝试自己为TF 'A a
定义Show实例,也会出现此错误。我搜索了“非法类型同义词”,还没有想出解决这个问题的方法。