[英]Haskell Map Function for Algebraic Data types
我有一个如下定义的代数数据类型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))
以上是我尝试实现此功能的尝试。 我无能为力了,我不明白我在做什么错。 任何帮助,将不胜感激。
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
Leaf . f
和Node
。
不使用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]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.