Haskell -将函数列表应用于变量

vm0i2vca  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(211)

我一直在尝试实现一个函数,它将一系列函数作为参数应用于一个给定的变量。我遇到了各种类型错误,类型无限多,类型不匹配。下面是使用递归的草稿,我相信它已经接近工作了,但是不断遇到类型不匹配。我被困在这个问题的沼泽里,不知道如何前进。

applyList :: [a -> b] -> a -> [b]
applyList [] variable = variable
applyList (f:fs) variable = applyList fs $(\f variable -> f variable)

这是我的另一个使用foldl的解决方案草案,也没有成功。

applyList :: [a -> a] -> a -> a
applyList fs variable = foldl (\variable f -> f variable) variable fs

示例用法:

applyList [] "foo" ==> "foo"
   applyList [] 1     ==> 1
   applyList [(++"bar")] "foo" ==> "foobar"
   applyList [reverse, tail, (++"bar")] "foo" ==> "raboo"
   applyList [(3*), (2^), (+1)] 0 ==> 6
   applyList [(+1), (2^), (3*)] 0 ==> 2
htrmnn0y

htrmnn0y1#

看起来您要编写两个不同的函数。让我们分别看一下它们。如果您需要此签名,

applyList :: [a -> b] -> a -> [b]

然后你想把每个函数应用于输入并得到一个结果列表。你不需要lambda。你可以简单地在递归的每一步把f应用于变量。

applyList :: [a -> b] -> a -> [b]
applyList [] _ = []
applyList (f:fs) variable = f variable : applyList fs variable

现在,Haskell提供了很多高级运算符来处理列表和数据结构,所以这种显式递归并不像你想象的那么频繁,特别是,你的applyList实际上就是map函数。

applyList :: [a -> b] -> a -> [b]
applyList fs a = map (\f -> f a) fs

\f -> f a可以短接至operator section

applyList :: [a -> b] -> a -> [b]
applyList fs a = map ($ a) fs

现在是第二个。如果这是你的目标

applyList :: [a -> a] -> a -> a

那么您需要一个fold是正确的。基于您的示例输入和输出,您似乎希望首先应用最右边的函数,因此我们可以使用foldr来实现它

applyList :: [a -> a] -> a -> a
applyList fs a = foldr (\f a -> f a) a fs

同样,\f a -> f a只是($)的一种可爱写法

applyList :: [a -> a] -> a -> a
applyList fs a = foldr ($) a fs

如果你现在还不清楚,不要担心。如果你对递归定义更熟悉的话,可以坚持使用它。这种更高层次的思考需要时间和经验,如果你坚持做你正在做的事情,我保证你会做到的。

xdyibdwo

xdyibdwo2#

记住列表的第一个元素应该是最外层的函数,这意味着你不需要向后做任何事情或者使用foldl。显式地写,它应该是这样的:

applyList [] variable = variable
applyList (f:fs) variable = f (applyList fs variable)

foldr一起:

applyList = foldr (.) id

相关问题