Haskell Labeled AST: No instance for (Show1 (Label a)), 如何构造实例?
Haskell Labeled AST: No instance for (Show1 (Label a)), How to construct an instance?
我想要一个带注释的AST,所以我定义了那些递归数据结构
使用 Fix
:
data Term a
= Abstraction Name a
| Application a a
| Variable Name
deriving (Read,Show,Eq,Functor,Foldable,Traversable)
data Label a b
= Label a (Term b)
deriving (Read,Show,Eq,Functor,Foldable,Traversable)
newtype Labeled a
= Labeled (Fix (Label a))
deriving (Show)
我希望能够show
一个Labeled a
,但是编译器不高兴:
No instance for (Show1 (Label a))
arising from the first field of `Labeled' (type `Fix (Label a)')
什么是 class Show1
以及如何定义能够显示 Labeled a
的适当实例?
Show1
is the class of what you might call "higher-order showables": type constructors which are showable whenever their argument is showable. For the purposes of fast-and-loose reasoning, you can think of Show1
as being declared roughly like this (see also showsPrec1
):
class Show1 f where
show1 :: Show a => f a -> String
这是另一种不准确但有用的思考方式Show1
。我正在使用 the constraints
library's "entailment" operator 来声明 f a
应该是 Show
的实例,只要 a
是。这个模型有点简单,但可能不太实用。
class Show1 f where
show1 :: Show a :- Show (f a)
无论如何,Fix :: (* -> *) -> *
是可显示的,如果它的参数是高阶可显示的。来自 the source code:
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
实例的最简单方法是使用 the deriving-compat
library's Template Haskell helper.
{-# 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
这样的库来管理您的术语语言中的名称和活页夹?)
我想要一个带注释的AST,所以我定义了那些递归数据结构
使用 Fix
:
data Term a
= Abstraction Name a
| Application a a
| Variable Name
deriving (Read,Show,Eq,Functor,Foldable,Traversable)
data Label a b
= Label a (Term b)
deriving (Read,Show,Eq,Functor,Foldable,Traversable)
newtype Labeled a
= Labeled (Fix (Label a))
deriving (Show)
我希望能够show
一个Labeled a
,但是编译器不高兴:
No instance for (Show1 (Label a)) arising from the first field of `Labeled' (type `Fix (Label a)')
什么是 class Show1
以及如何定义能够显示 Labeled a
的适当实例?
Show1
is the class of what you might call "higher-order showables": type constructors which are showable whenever their argument is showable. For the purposes of fast-and-loose reasoning, you can think of Show1
as being declared roughly like this (see also showsPrec1
):
class Show1 f where
show1 :: Show a => f a -> String
这是另一种不准确但有用的思考方式Show1
。我正在使用 the constraints
library's "entailment" operator 来声明 f a
应该是 Show
的实例,只要 a
是。这个模型有点简单,但可能不太实用。
class Show1 f where
show1 :: Show a :- Show (f a)
无论如何,Fix :: (* -> *) -> *
是可显示的,如果它的参数是高阶可显示的。来自 the source code:
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
实例的最简单方法是使用 the deriving-compat
library's Template Haskell helper.
{-# 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
这样的库来管理您的术语语言中的名称和活页夹?)