简短形式(这将至少以一种方式解决我的问题)
我该怎么做这样的事情:
try_to_show :: a -> String
try_to_show val = if (val is instance of Show) (show val) else "Cannot show"
我可能完全错误地这样做了(unhaskell 方式);我只是在学习,所以请让我知道是否有更好的方法来解决这个问题。
上下文:我正在写一堆树结构。我想将我的prettyprint
函数重用于二叉树。并非所有的树都可以使用泛型Node
/Branch
数据类型;不同的树需要不同的额外数据。因此,为了重用prettyprint
我想创建一个类的函数,不同的树将是以下实例:
class GenericBinaryTree a where
is_leaf :: a -> Bool
left :: a -> a
node :: a -> b
right :: a -> a
这样他们只需要实现获取左、右和当前节点值的方法,而prettyprint不需要知道内部结构。
然后我来到这里:
prettyprint_helper :: GenericBinaryTree a => a -> [String]
prettyprint_helper tree
| is_leaf tree = []
| otherwise = ("{" ++ (show (node tree)) ++ "}") : (prettyprint_subtree (left tree) (right tree))
where
prettyprint_subtree left right =
((pad "+- " "| ") (prettyprint_helper right)) ++ ((pad "`- " " ") (prettyprint_helper left))
pad first rest = zipWith (++) (first : repeat rest)
我得到了Ambiguous type variable 'a0' in the constraint: (Show a0) arising from a use of 'show'
错误(show (node tree))
这是最基本的树数据类型和实例定义的示例(我的其他树有其他字段但它们与通用prettyprint
函数无关)
data Tree a
= Branch (Tree a) a (Tree a)
| Leaf
instance GenericBinaryTree (Tree a) where
is_leaf Leaf = True
is_leaf _ = False
left (Branch left node right) = left
right (Branch left node right) = right
node (Branch left node right) = node
我本可以node :: a -> [String]
在每个实例/类型的树中定义和处理字符串化,但这感觉更整洁。就 而言prettyprint
,我只需要一个字符串表示,但如果我稍后添加其他通用二叉树函数,我可能需要实际值。
那么,无论节点值是否为实例,我如何编写它才能工作Show
?或者我应该以什么其他方式来解决这个问题?在面向对象的语言中,我可以很容易地检查一个类是否实现了某些东西,或者一个对象是否有一个方法。
我不能使用类似的东西
prettyprint :: Show a => a -> String
因为需要显示的不是树,而是树内部的值(由 function 返回node
)需要显示。我还尝试更改node
为Show b => a -> b
没有运气(以及一堆其他类型的类/先决条件/无论如何/我什至不知道我在做什么)。