我有一个如下定义的代数数据类型Newb。现在我想为其编写一个自定义的map函数而不使用递归。此外,我还有一个foldNewb函数也可以提供帮助。
data Newb a = Leaf a | Node [Newb a]
foldNewb:: (a->b)->([b]->b)->Newb a -> b
foldNewb f _ (Leaf a) = f a
foldNewb f1 f2 (Node a) = f2 (map (foldNewb f1 f2) a)
Newbmap :: (a->b)-> Newb a -> Newb b
Newbmap f (Leaf a) = (Leaf (f a))
Newbmap f (Node a) = (Node (foldNewb f concat a))
上面是我实现该功能的尝试。我无能为力了,我不明白我在做什么错。任何帮助将不胜感激。
答案 0 :(得分:5)
tl; dr 这是您的功能。但是我建议继续阅读以了解我是如何提出的,以便您可以进行思考。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f = foldNewb (Leaf . f) Node
您已经很接近了,并且正确使用了foldNewb
,但是您想得太多了。
首先,您无法命名函数Newbmap
。大写名称保留用于类型。因此,我们将其称为newbmap
。现在,foldNewb
已经处理了Leaf
和Node
这两种情况,因此我们根本不必在newbmap
中进行模式匹配。实际上,您的第一个newbmap
情况确实可以完成foldNewb
的工作,因此,让我们考虑第二个情况。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f (Node a) = (Node (foldNewb f concat a))
我们想折叠我们的数据结构。特别是,我们希望fold调用完全产生新的数据结构。最后,我们 无需明确使用Node
,因为foldNewb
已经对我们有用。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f a = foldNewb f concat a
现在,在第一种情况下,我们需要一个函数a -> Newb b
(因为结果将是Newb b
类型)。您已通过f :: a -> b
,它非常接近您想要的。我们只需要用一个函数b -> Newb b
来组成它,Leaf
就可以做到这一点。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f a = foldNewb (Leaf . f) concat a
对于第二个参数,您需要[Newb b] -> Newb b
,这很容易由Node
完成。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f a = foldNewb (Leaf . f) Node a
而且(尽管没什么区别),我们可以指向最后一个参数。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f = foldNewb (Leaf . f) Node
因此有一个有效的newbmap
函数。现在,关于我如何提出所有这些类型,如果您使用的是GHC,则有一个非常有用的功能,称为“ 类型孔”,您可以使用它来识别所需的类型。所以(如果您编写函数,我在调试功能时就做到了)
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f = foldNewb _1 _2
然后,您会收到非常具体的GHC消息,告诉您_1 :: a -> Newb b
和_2 :: [Newb b] -> Newb b
。然后,您面临的挑战就是简单地找到具有这些特定类型的函数。这是我提出Leaf . f
和Node
的地方。
答案 1 :(得分:1)
不使用foldNewb
:
data Newb a = Leaf a | Node [ Newb a]
deriving (Show)
newbMap :: (a -> b) -> Newb a -> Newb b
newbMap f (Leaf a) = Leaf (f a)
-- since a :: [Newb a] in the below clause, we can map (newbMap f) over the elements
newbMap f (Node a) = Node (map (newbMap f) a)
tree = Node [ Leaf 1, Node [Leaf 2, Leaf 3], Leaf 4]
mapped = newbMap (+1) tree -- Node [Leaf 2,Node [Leaf 3,Leaf 4],Leaf 5]