Haskell 漂亮打印机类实例的绑定
如何为以下实例创建绑定?在这一点上,我正在寻找任何可以编译的绑定解决方案,以便开始理解我的错误。我的全部代码是:Haskell 漂亮打印机类实例的绑定,haskell,Haskell,如何为以下实例创建绑定?在这一点上,我正在寻找任何可以编译的绑定解决方案,以便开始理解我的错误。我的全部代码是: {-# OPTIONS_GHC -Wall #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE ConstrainedClassMethods #-} {-# LANGUAGE InstanceSigs #-} module Tagless where import Data.
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ConstrainedClassMethods #-}
{-# LANGUAGE InstanceSigs #-}
module Tagless where
import Data.Text.IO as T
import Data.Text.Prettyprint.Doc.Render.Text
data Exp = B Bool
| MyInt Int
data Doc ann
class Pretty a where
pretty :: Show a => a -> Doc ann
prettyList :: [a] -> Doc ann
instance Pretty Bool where
pretty :: Bool -> Doc ann
prettyList :: [Bool] -> Doc ann
我尝试了以下几种类型和变体,但得到了多个不匹配的类型。1) 既然B是Bool Exp,为什么不能使用它呢?2) 如何创建与文档匹配的绑定
instance Pretty Bool where
pretty :: Bool -> Doc ann
prettyList :: [Bool] -> Doc ann
pretty (B e1) = e1
prettyList [B e1] = e1
我正在使用package您正在重新定义
Doc
类型和Pretty
类,因此首先您应该删除数据
和类
定义,并使用从数据.Text.Prettyprint.Doc
导入的定义(或者在库的较新版本中使用Prettyprinter
)。接下来,您要为Exp
创建的实例,而当前您正在为Bool
编写一个实例(该实例已经存在):
通过对Exp
类型进行模式匹配,并为每个构造函数定义所需的漂亮打印,可以定义pretty
。例如,如果您只想显示布尔数和整数及其默认的Pretty
实例,只需对从Exp
提取的值调用Pretty
:
pretty exp = case exp of
B bool -> pretty bool -- (1)
MyInt int -> pretty int -- (2)
请注意,(1)和(2)处对pretty
的调用是不同的实例:第一个是pretty::Bool->Doc ann
,第二个是pretty::Int->Doc ann
。通过使用prettyprinter
中的prettyprinter
或类似hcat
//hsep
//vcat
//缩进
/…等组合器,您可以为一个类型构建一个漂亮的打印实例。因此,把所有这些放在一起:
instance Pretty Exp where
pretty :: Exp -> Doc ann
pretty exp = case exp of
B bool -> pretty bool
MyInt int -> pretty int
或者,以等式方式而不是使用大小写
:
pretty (B bool) = pretty bool
pretty (MyInt int) = pretty int
既然B是Bool Exp,为什么不能使用它呢
B
是类型为Bool->Exp
的构造函数,因此像B e1
这样的表达式通过包装e1
生成类型为Exp
的值,该值必须是Bool
;类似地,模式be1
匹配B
构造函数,并提取其字段e1
,该字段也是Bool
类型。所以当你写这篇文章时:
pretty (B e1) = e1
您刚才说的是“提取Bool
字段并返回它”,但您试图在需要Doc
时返回Bool
。(即,此定义的类型为Exp->Bool
,但签名需要Exp->Doc ann
)
您可能会发现使用GADTSyntax
来定义数据类型更为清晰,因为它允许您将每个构造函数的类型显式写出为FieldType1->…->FieldTypeN->TypeName
,例如:
{-# LANGUAGE GADTSyntax #-}
data Exp where
B :: Bool -> Exp
MyInt :: Int -> Exp
这正是您在GHCi中询问构造函数类型时得到的签名:
> :type MyInt
MyInt :: Int -> Exp
这是非常有益的。非常感谢。我试着运行你的解决方案,得到了“不在范围内:类型构造函数或类”Pretty“,所以我假设导入对我不起作用,因为类没有导入,它对你起作用了吗?@pmichaels:如果你查看包的文档,你会发现,所以你应该从那里导入它。要获得我在这里使用的内容,可以编写import Data.Text.Prettyprint.Doc(Doc,Pretty(…)
。您可能希望导入库的其他部分qualified
并使用缩写,例如import qualified Data.Text.Prettyprint.Doc作为Pretty
或…作为P
,因此名称的来源总是很清楚,例如,Pretty.nest
/P.nest
。我已经做了一些导入更新,现在可以使用了。再次感谢您的澄清。
{-# LANGUAGE GADTSyntax #-}
data Exp where
B :: Bool -> Exp
MyInt :: Int -> Exp
> :type MyInt
MyInt :: Int -> Exp