为 ADT 派生显示实例不适用于高级类型族



我只是使用此处提供的默认示例要点来研究 Chris Done 的 ADT,遇到了一个问题:我的 ADT 具有由高级类型族定义的字段,无法使用派生 show 实例。GHC 告诉我我需要为类型系列派生一个 Show 实例,但我不确定该怎么做。这是我所拥有的,到目前为止,任何评论都会有所帮助。

在下面的示例(使用ghc 8.8.1(中,目标是定义Show的实例 forShowMe,如果可能,请使用 派生。

{-# 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)

如果我只是尝试自己定义 Show 实例以TF 'A a.我已经搜索了"非法类型同义词",但没有想出解决这个问题的方法。

你需要添加

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE UndecidableInstances #-}

然后向GHC建议所需的上下文:

deriving instance Show (TF p String) => Show (ShowMe p)

GHC不会自动添加该上下文,因为它可能会让程序员感到惊讶。

最新更新