在 Haskell 编程中,Graham Hutton 定义了列表的展开,如下所示:
unfold :: (b -> Bool ) -> (b -> a) -> (b -> b) -> b -> [a]
unfold p h t x | p x = []
| otherwise = h x : unfold p h t (t x)
定义一个函数
• listUnfold :: (b -> Bool) -> (b -> a) -> (b -> b) -> b -> [a]
与上面的类似,但在其实现中使用unfoldr并且是非递归的。
我已经尝试解决上述问题有一段时间了,但我仍然可以设法做到这一点(在 Haskell 和一般函数式编程中相当新)。
我的尝试:
listUnfold :: (b -> Bool) -> (b -> a) -> (b -> b) -> b -> [a]
listUnfold f h t x
| f x == True = []
| otherwise = h x :
listUnfoldr (\x -> if f x then Nothing else Just ((h x), (t x))) x
在英语中,如果 f x
为 true,则返回空列表。否则,使用 h x
作为头部,并附加展开器的结果作为尾部。 Unfoldr 接受一个列表 (x:xs)
,该列表应以 x
作为头部,以 xs
作为尾部进行递归。
p/s:我可能做得非常非常错误。
最佳答案
你已经快明白了!原始函数使用函数 p
(表示“谓词”)来确定我们是否已完成展开,使用 h
应用于每个元素,使用 t
code> (“转换”)将元素转换为列表其余部分的种子。
unfoldr
需要一个函数 f::b -> Maybe (a,b)
,如果我们完成则返回 Nothing
展开,或 Just (x, y)
,其中 x
是要添加到列表中的元素,y
是其余元素的种子列表。
因此,unfoldr
中的 f
负责 p
、h
和 所有三个的功能>t
。 Nothing
-or-Just
二分法扮演 bool 函数 p
的角色,元组的第二个元素扮演 t
的工作是为列表的其余部分提供种子。
这是我的解决方案(为了清楚起见,我已重命名了您问题中的变量):
listUnfold pred f trans seed =
unfoldr (\x -> if pred x
then Nothing
else Just (f x, trans x)) seed
当然,当一个值出现在定义的右侧时,就像这里的seed一样,您可以利用Haskell的柯里化(Currying)语法,并将其完全丢弃:
listUnfold pred f trans = unfoldr (\x -> if pred x
then Nothing
else Just (f x, trans x))
正式而言,此转换称为 eta reduction .
关于haskell - 硬件 : Unfolding a list in a specific way,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15537100/