我正在尝试构造一个本质上是二叉树的数据类型,其中:每个节点的左分支是一个函数,可以作用于每个节点的右分支中的变量.我是Haskell的新手,我不确定我是否会以正确的方式解决这个问题,但我目前的问题是我无法弄清楚如何将我的类型添加到Show类型类中.这是我的尝试:
{-# LANGUAGE ExistentialQuantification #-}
-- file: TS.hs
data TypeSentence a = forall b. Apply (TypeSentence (b->a)) (TypeSentence b)
| Expr a
instance (Show a) => (Show (TypeSentence a)) where
show (Expr x) = show x
show (Apply x y) = (show x) ++ " " ++ (show y)
instance (Show (TypeSentence b->a)) where
show (Expr x) = show "hello"
x = Expr 1
f = Expr (+1)
s = Apply f x
Run Code Online (Sandbox Code Playgroud)
但是,当我将其加载到ghci时,我收到以下错误:
TS.hs:9:24:
Could not deduce (Show (b -> a)) from the context ()
arising from a use of `show' at TS.hs:9:24-29
Possible fix:
add (Show (b -> a)) to the context of the constructor `Apply'
or add an instance declaration for (Show (b -> a))
In the first argument of `(++)', namely `(show x)'
In the expression: (show x) ++ " " ++ (show y)
In the definition of `show':
show (Apply x y) = (show x) ++ " " ++ (show y)
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
我是如何添加Show(b-> a)声明的?
谢谢.
您编写的代码存在一些问题,因此我将逐一介绍它们.
您无法为其添加特别丰富的实例Show (a -> b).考虑一下如何写它:
instance Show (a -> b) where
show f = error "What goes here?"
Run Code Online (Sandbox Code Playgroud)
既然f是一个函数,除了将它应用于一个值之外,你无法用它做任何事情; 并且由于a是完全多态的类型,因此无法创建a要应用的类型值f.所以你唯一的选择是这样的
instance Show (a -> b) where
show _ = "<function>"
Run Code Online (Sandbox Code Playgroud)
正如Daniel Fischer在评论中所说,这可以在Text.Show.Functions模块中找到.不过,我真的不打扰这个; 我只想写点什么
instance Show a => Show (TypeSentence a) where
show (Apply _ x) = "Apply _ " ++ show x -- This still won't work; see below
show (Expr x) = "Expr " ++ show x
Run Code Online (Sandbox Code Playgroud)
既然show只能为任何函数返回一个字符串,只需直接内联即可.
尽管如此,你仍然无法编写那个Show实例.如果您尝试编译上面的实例,则会收到以下错误:
TS.hs:8:36:
Could not deduce (Show b) arising from a use of `show'
from the context (Show a)
bound by the instance declaration
at TS.hs:7:10-40
Possible fix:
add (Show b) to the context of
the data constructor `Apply'
or the instance declaration
In the second argument of `(++)', namely `show x'
In the expression: "Apply _ " ++ show x
In an equation for `show': show (Apply _ x) = "Apply _ " ++ show x
Run Code Online (Sandbox Code Playgroud)
问题是,在你的定义中TypeSentence,Apply隐藏了一个由任意存在隐藏类型参数化的变量(x在定义中绑定show).但是不能保证可以显示,所以不会进行类型检查,这是上面产生的错误:没有实例,因为它是任意的.因此,要摆脱这种情况,最简单的方法就是TypeSentencebbshow xShow bb
instance Show a => Show (TypeSentence a) where
show (Apply _ _) = "Apply _ _"
show (Expr x) = "Expr " ++ show x
Run Code Online (Sandbox Code Playgroud)
这并不是特别有用.所以也许没有一个好的Show实例TypeSentence.(这没关系.许多有用的类型都没有Show实例.)
这个与其他一切无关.该instance Show (TypeSentence b -> a)声明试图宣布的一个实例Show为从函数TypeSentence b到a; 如果你重新表达为instance Show (TypeSentence (b -> a)),你仍然需要FlexibleInstances和OverlappingInstances扩展来获得编译.所以你应该只是斧头.