Haskell:我如何定义我的函数可以作为参数的类型?以及如何在数据结构中访问未命名的变量?

时间:2009-11-23 19:52:38

标签: haskell function

1)这是我的代码,find函数需要将(节点a)和类型(a)作为参数,但我的函数定义似乎不起作用,我做错了什么?我能找到的网上信息很少,所以感谢您的帮助!

2)当我的find函数实现时,我需要访问Node中的特定变量,我该怎么办?!

-- int for comparisons
find :: (Node a) => Node a -> a -> Bool
find n s
| s == "asd" = True
| s /= "asd" = False

data Node a = Node a (Node a) (Node a)
| Empty

myTree = Node "parent" (Node "left" Empty Empty)
(Node "right" Empty Empty)

以下是我收到的错误消息:

Type constructor `Node' used as a class
In the type `(Node a) => Node a -> a -> Bool'
In the type signature for `find':
find :: (Node a) => Node a -> a -> Bool
Failed, modules loaded: none.

我显然还在学习这个,所以对解决方案的解释也会受到赞赏,谢谢你!

3 个答案:

答案 0 :(得分:5)

语法

Node a => ...

意味着Node是类型类,但事实上,它只是一种普通的数据类型。

因此这个签名就足够了

find :: Node a -> a -> Bool

示例:

find (Node val left right) = ...
find Empty = ...

答案 1 :(得分:3)

问题#1

...
find :: (Node a) => Node a -> a -> Bool

'(节点a)=>' bit说 a 可以是任何东西,只要它实现 Node 类型类。您的代码没有定义任何名为 Node 的类型类,因此最快的方法是删除该约束:

...
find :: Node a -> a -> Bool
find n s

但是,由于您使用 s 所做的事情,您将收到更多错误:

....
| s == "asd" = True

你的类型签名说 s 可以是任何东西,但是你试图用“asd”测试它是否相等,这意味着 s 必须是一个字符串。将类型签名更改为以下内容将允许您的代码进行编译,但可能无法完成您想要的任务。

find :: Node a -> String -> Bool
...

问题#2

看起来您的目标是以递归方式扫描 Node 结构测试是否与某些已知值相等,直到找到所需内容。以下是该函数应该看起来的前两行。

find :: (Eq a) => Node a -> a -> Bool
find (Node n _ _) s | n == s = True
...

“(Eq a)=>”表示 a 必须是为其定义的 == / = 等。

第二行演示了如何“访问节点中的特定变量”的问题。您使用Haskell的一个名为“模式匹配”的功能来构建一个参数应该是什么样子的模板。然后,编译器将实际参数与您提供的模板相匹配。

答案 2 :(得分:0)

在dario的帮助下,这里提供的是我的最终解决方案

find :: (Eq a) => Node a -> a -> Bool
find (Node val left right) s
    | s == val      = True
    | s /= val      = False