Haskell 树木地图

发布于 2024-12-07 11:54:22 字数 1022 浏览 1 评论 0原文

我的树是由

data Tree a = Leaf a | Node (Tree a) (Tree a) 
        deriving (Show)

我还声明一个测试树定义的。

myTree = Node (Node (Leaf 1) (Leaf 2)) (Leaf 3)

我想要做的是创建一个函数 maptree f 它将作用于 Leaf。更具体地说,fx = x +1

那么maptree f myTree将返回

Node (Node (Leaf 2) (Leaf 3)) (Leaf 4)

我的解决方案是,

maptree f (Leaf a)= Leaf (f a)
maptree f (Node xl xr ) = Node (maptree xl) (maptree xr)

但它会返回以下错误

Couldn't match expected type `Tree a'
       against inferred type `Tree t -> Tree t'
Probable cause: `maptree' is applied to too few arguments
In the first argument of `Node', namely `(maptree xl)'
In the expression: Node (maptree xl) (maptree xr)

失败,模块已加载:无。

然而,如果我这样做的话,

maptree (Leaf a)= Leaf ( a + 1)
maptree (Node xl xr ) = Node (maptree xl) (maptree xr)

它确实有效。

我看不出第一个功能和第二个功能之间的区别。我如何得到错误?谢谢。

My tree is defined by

data Tree a = Leaf a | Node (Tree a) (Tree a) 
        deriving (Show)

I also declare a testing tree.

myTree = Node (Node (Leaf 1) (Leaf 2)) (Leaf 3)

What I want to do is create a function maptree f which will act on Leaf. To be more specifically, f x = x +1,

then maptree f myTree will return

Node (Node (Leaf 2) (Leaf 3)) (Leaf 4)

My solution is

maptree f (Leaf a)= Leaf (f a)
maptree f (Node xl xr ) = Node (maptree xl) (maptree xr)

but it will return the following error

Couldn't match expected type `Tree a'
       against inferred type `Tree t -> Tree t'
Probable cause: `maptree' is applied to too few arguments
In the first argument of `Node', namely `(maptree xl)'
In the expression: Node (maptree xl) (maptree xr)

Failed, modules loaded: none.

However, if I do

maptree (Leaf a)= Leaf ( a + 1)
maptree (Node xl xr ) = Node (maptree xl) (maptree xr)

it does work out.

I can not see the difference between the first function and the second one. How do I get error? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伪装你 2024-12-14 11:54:22

您缺少递归映射树调用上的函数:

maptree f (Leaf a)= Leaf (f a) 
maptree f (Node xl xr ) = Node (maptree xl) (maptree xr)

应该是

maptree f (Leaf a)= Leaf (f a) 
maptree f (Node xl xr ) = Node (maptree f xl) (maptree f xr)

You are missing the function on the recursive maptree calls:

maptree f (Leaf a)= Leaf (f a) 
maptree f (Node xl xr ) = Node (maptree xl) (maptree xr)

should be

maptree f (Leaf a)= Leaf (f a) 
maptree f (Node xl xr ) = Node (maptree f xl) (maptree f xr)
霓裳挽歌倾城醉 2024-12-14 11:54:22

请注意,这是 Tree 类型的 Functor 实例的明显 fmap。因此,您可以使用 DeriveFunctor 扩展让 GHC 为您生成它。

{-# LANGUAGE DeriveFunctor #-}
data Tree a = Leaf a | Node (Tree a) (Tree a) 
    deriving (Functor, Show)

我们来试试吧。

*Main> fmap (+1) (Node (Node (Leaf 1) (Leaf 2)) (Leaf 3))
Node (Node (Leaf 2) (Leaf 3)) (Leaf 4)

Note that this is the obvious fmap of a Functor instance for your Tree type. You can therefore use the DeriveFunctor extension to have GHC generate it for you.

{-# LANGUAGE DeriveFunctor #-}
data Tree a = Leaf a | Node (Tree a) (Tree a) 
    deriving (Functor, Show)

Let's try it.

*Main> fmap (+1) (Node (Node (Leaf 1) (Leaf 2)) (Leaf 3))
Node (Node (Leaf 2) (Leaf 3)) (Leaf 4)
尾戒 2024-12-14 11:54:22

当您更深地递归时(对于这种高阶函数),不忘记传递函数的一种愚蠢方法是使用助手:

maptree f (Leaf a)     = Leaf (f a)
maptree f (Node xl xr) = Node (go xl) (go xr)
    where go = maptree f

或者,或者(也许更常见):

maptree f tree = go tree                      -- or eta reduce:   maptree f = go
    where go (Leaf a)     = Leaf (f a)
          go (Node xl xr) = Node (go xl) (go xr)

在第一个示例中,我使用 go 有点像 maptree f 的宏。在第二个示例中,我利用了 maptree 的输入 f 位于 go 函数内部的事实,因为 gomaptreewhere 子句中声明。

One dumb way to not forget to pass along the function as you recurse deeper (for this sort of higher-order function) is to use a helper:

maptree f (Leaf a)     = Leaf (f a)
maptree f (Node xl xr) = Node (go xl) (go xr)
    where go = maptree f

Or, alternatively (and perhaps more commonly):

maptree f tree = go tree                      -- or eta reduce:   maptree f = go
    where go (Leaf a)     = Leaf (f a)
          go (Node xl xr) = Node (go xl) (go xr)

In the first example, I use go sort of as a macro for maptree f. In the second example, I take advantage of the fact that maptree's input f is in scope inside the go function because go is declared in a where clause of maptree.

陈甜 2024-12-14 11:54:22

错误消息基本上告诉您出了什么问题:您没有传递 maptree 足够的参数。定义maptree f (Node xl xr) 表示maptree 接受两个参数:一个函数和一棵树。但是,当您像 maptree xl 那样调用它时,您只给它一个参数(一棵树)。

在第二个版本中,您将 maptree 定义为仅接受一个参数(一棵树),这就是它不会产生该错误的原因。

例如,您可以通过调用 maptree f xl 而不是 maptree xl 来解决问题。

The error message basically tells you what's wrong: you are not passing maptree enough arguments. The definition maptree f (Node xl xr) says that maptree takes two arguments, a function and a tree. But when you call it like maptree xl, you're only giving it one argument (a tree).

In your second version, you've defined maptree to only take one argument (a tree), which is why it doesn't produce that error.

You can fix your problem by, for example, calling maptree f xl instead of maptree xl.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文