简体   繁体   English

代数数据类型的Haskell映射函数

[英]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已经处理了LeafNode这两种情况,因此我们根本不必在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 bLeaf就会做到这一点。

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 . fNode

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM