繁体   English   中英

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

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

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

不使用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