Show1
是你可能称之为“高阶可显示对象”的类:类型构造函数,只要它们的参数是可显示的,就可以显示。出于快速和宽松推理的目的,您可以将其Show1
视为大致如下声明(另请参见 参考资料showsPrec1
):
class Show1 f where
show1 :: Show a => f a -> String
这是另一种不准确但有用的思考方式Show1
。我正在使用library的constraints
“ entailment”运算符来声明它f a
应该是Show
when a
is 的一个实例。这个模型有点简单,但可能不太实用。
class Show1 f where
show1 :: Show a :- Show (f a)
无论如何,Fix :: (* -> *) -> *
如果它的论点是一个高阶可显示的,它就是可显示的。从源代码:
instance Show1 f => Show (Fix f) where
showsPrec d (Fix a) =
showParen (d >= 11)
$ showString "Fix "
. showsPrec1 11 a
的作者本recursion-schemes
可以用来StandaloneDeriving
编写他们的Show
实例...
deriving instance Show (f (Fix f)) => Show (Fix f)
...但是这种情况需要UndecidableInstances
.
Show1
为给定函子编写实例的最简单方法是使用库deriving-compat
的Template Haskell 助手。
{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
{-# LANGUAGE TemplateHaskell #-}
import Text.Show.Deriving
import Data.Functor.Foldable
type Name = String
data Term a
= Abstraction Name a
| Application a a
| Variable Name
deriving (Read, Show, Eq, Functor, Foldable, Traversable)
deriveShow1 ''Term
data Label a b = Label a (Term b)
deriving (Read, Show, Eq, Functor, Foldable, Traversable)
deriveShow1 ''Label
newtype Labeled a = Labeled (Fix (Label a)) deriving (Show)
这将生成以下实例,
instance Show1 Term
instance Show a => Show1 (Label a)
为您提供您想要Labeled
的派生实例:
instance Show a => Show (Labeled a)
(PS。你有没有考虑过使用一个库bound
来管理你的术语语言中的名称和活页夹?)