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

Mel*_*met 1 haskell functional-programming

我一直在尝试实现一个函数,该函数将作为参数给出的函数列表应用于给定变量。我遇到了无限类型和类型不匹配的各种类型错误。下面是使用递归的草稿,我相信已经接近工作,但继续遇到类型不匹配的情况。我陷入了这个问题的泥潭,不知道如何取得进展。

applyList :: [a -> b] -> a -> [b]
applyList [] variable = variable
applyList (f:fs) variable = applyList fs $(\f variable -> f variable)
Run Code Online (Sandbox Code Playgroud)

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

applyList :: [a -> a] -> a -> a
applyList fs variable = foldl (\variable f -> f variable) variable fs
Run Code Online (Sandbox Code Playgroud)

用法示例:

   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
Run Code Online (Sandbox Code Playgroud)

Sil*_*olo 6

看起来您正在尝试编写两个不同的函数。让我们分别来看一下。如果你想要这个签名,

applyList :: [a -> b] -> a -> [b]
Run Code Online (Sandbox Code Playgroud)

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

applyList :: [a -> b] -> a -> [b]
applyList [] _ = []
applyList (f:fs) variable = f variable : applyList fs variable
Run Code Online (Sandbox Code Playgroud)

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

applyList :: [a -> b] -> a -> [b]
applyList fs a = map (\f -> f a) fs
Run Code Online (Sandbox Code Playgroud)

并且\f -> f a可以短接至操作员部分

applyList :: [a -> b] -> a -> [b]
applyList fs a = map ($ a) fs
Run Code Online (Sandbox Code Playgroud)

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

applyList :: [a -> a] -> a -> a
Run Code Online (Sandbox Code Playgroud)

那么你想要弃牌是对的。根据您的示例输入和输出,您似乎希望首先应用最右边的函数,因此我们可以使用foldr

applyList :: [a -> a] -> a -> a
applyList fs a = foldr (\f a -> f a) a fs
Run Code Online (Sandbox Code Playgroud)

再说一次,\f a -> f a这只是一种可爱的写作方式($)

applyList :: [a -> a] -> a -> a
applyList fs a = foldr ($) a fs
Run Code Online (Sandbox Code Playgroud)

如果您现在还不清楚,请不要担心。如果您对此更满意,请坚持使用您的递归定义。这种更高层次的思考伴随着 Haskell 的时间和经验而来,如果你继续做你正在做的事情,我保证你会到达那里。