[英]Haskell Map Function for Algebraic Data types
I have an algebraic data type Newb defined like below. 我有一个如下定义的代数数据类型Newb。 Now I want to write a custom map function for it without using recursion.Further I have a foldNewb function which could also help. 现在我想为其编写一个自定义的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))
above is my attempt at implementing this function. 以上是我尝试实现此功能的尝试。 I can't get any further than this and I don't understand what I'm doing wrong here. 我无能为力了,我不明白我在做什么错。 Any help would be appreciated. 任何帮助,将不胜感激。
tl;dr Here's your function. tl; dr这是您的功能。 But I recommend reading on to see how I came up with this, so you can work out the thought process. 但我建议继续阅读以了解我是如何提出的,以便您可以进行思考。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f = foldNewb (Leaf . f) Node
You're pretty close, and you're using foldNewb
correctly, but you're overthinking it. 您已经很接近了,并且正确使用了foldNewb
,但是您考虑得太多了。
First, you can't name a function Newbmap
. 首先,您不能将函数命名为Newbmap
。 Capital names are reserved for types. 大写名称保留用于类型。 So we'll call it newbmap
. 因此,我们将其newbmap
。 Now, foldNewb
already handles both of the cases Leaf
and Node
, so we shouldn't have to pattern match in newbmap
at all. 现在, foldNewb
已经处理了Leaf
和Node
这两种情况,因此我们根本不必在newbmap
中进行模式匹配。 In fact, your first newbmap
case does exactly what foldNewb
would do anyway, so let's just consider the second case. 实际上,您的第一个newbmap
案例完全可以完成foldNewb
,因此,让我们考虑第二个案例。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f (Node a) = (Node (foldNewb f concat a))
We want to fold over our data structure. 我们想折叠我们的数据结构。 In particular, we want our fold call to completely produce the new data structure. 特别是,我们希望fold调用完全产生新的数据结构。 We shouldn't need to explicitly use Node
at the end, since, again, foldNewb
already does that work for us. 我们不应该需要明确地使用Node
末,因为再次, foldNewb
已经这样做是为我们工作。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f a = foldNewb f concat a
Now in the first case, we need a function a -> Newb b
(since the result is going to be of type Newb b
). 现在,在第一种情况下,我们需要一个函数a -> Newb b
(因为结果将是Newb b
类型)。 You've passed f :: a -> b
, which is very close to what you want. 您已经通过了f :: a -> b
,它非常接近您想要的。 We simply need to compose it with a function b -> Newb b
, and Leaf
will do exactly that. 我们只需要使用功能b -> Newb b
, Leaf
就会做到这一点。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f a = foldNewb (Leaf . f) concat a
For the second argument, you want [Newb b] -> Newb b
, which again is very easily done by Node
. 对于第二个参数,您需要[Newb b] -> Newb b
,这又很容易由Node
完成。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f a = foldNewb (Leaf . f) Node a
And (although it doesn't make a difference), we can pointfree the final argument. 并且(尽管没有任何区别),我们可以指向最后一个参数。
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f = foldNewb (Leaf . f) Node
So there's a working newbmap
function. 因此,有一个有效的newbmap
函数。 Now, as for how I came up with all of those types, if you're using GHC, there's a very helpful feature called type holes that you can use to identify what sort of types you need. 现在,关于我如何提出所有这些类型,如果您使用的是GHC,则有一个非常有用的功能,称为类型孔 ,可用于识别所需的类型。 So (and I did exactly this when debugging your function) if you write 所以(如果您编写函数,我在调试函数时正是这样做的)
newbmap :: (a->b)-> Newb a -> Newb b
newbmap f = foldNewb _1 _2
then you'll get very specific GHC messages telling you _1 :: a -> Newb b
and _2 :: [Newb b] -> Newb b
. 那么您会得到非常具体的GHC消息,告诉您_1 :: a -> Newb b
和_2 :: [Newb b] -> Newb b
。 Then your challenge is simply to find functions with those particular types. 然后,您面临的挑战就是简单地找到具有这些特定类型的函数。 And this is where I came up with Leaf . f
这就是我Leaf . f
Leaf . f
and Node
. Leaf . f
和Node
。
Without using foldNewb
: 不使用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.