Haskell 应用于参数的函数列表

Haskell 应用于参数的函数列表,haskell,Haskell,任务是生成函数,获取一元函数列表(+1,*2等)(至少3个),并将它们一致地应用于参数。例如:func 1[(+1),(+1),(/2)]==1.5。这是我做的: compose x [(y),(c),(z)] = map ($ x) [(z) . (c) . (y)] 但是我怎样才能制作无限的函数列表呢?如果用户想要3个以上的功能。 另一个问题是,此函数返回一个元素而不是一个元素的列表([4]而不是4),我有点被它卡住了 compose x ys = foldl (\a b -> b

任务是生成函数,获取一元函数列表(+1,*2等)(至少3个),并将它们一致地应用于参数。例如:func 1[(+1),(+1),(/2)]==1.5。这是我做的:

compose x [(y),(c),(z)] =  map ($ x) [(z) . (c) . (y)]
但是我怎样才能制作无限的函数列表呢?如果用户想要3个以上的功能。
另一个问题是,此函数返回一个元素而不是一个元素的列表([4]而不是4),我有点被它卡住了

compose x ys = foldl (\a b -> b a) x ys
这可以简化为

compose = foldl (\a b -> b a)
或者

compose x [] = x
compose x (y:ys) = compose (y x) ys
它将函数应用于输入,然后将该输入用作下一个输入,直到到达列表末尾,然后返回最终值

λ> compose 1 [(+1), (+1), (/2)]
1.5
λ> compose 1 [(+1), (+1), (/2), (*10), (+(-1))]
14.0
λ> compose 1 []
1
λ> 
因为haskell是如何解析负数的,我认为你必须通过添加负数来构造负数函数

如果用户必须输入至少3个功能,则可以执行以下操作:

compose x ys
    | length ys < 3 = error "Must enter at least 3 functions!"
    | otherwise = foldl (\a b -> b a) x ys
composexys
|长度ys<3=错误“必须输入至少3个函数!”
|否则=foldl(\a b->b a)x ys
或者,您可以返回一个Maybe,因为在可恢复的内容上出错不是很好的风格

compose x ys
    | length ys < 3 = Nothing
    | otherwise = Just $ foldl (\a b -> b a) x ys
composexys
|长度ys<3=无
|否则=仅$foldl(\a b->b a)x ys
一般问题 您可以为此使用
foldl
:在这种情况下,您将累加器从左向右传递到列表上,并对其执行一些操作:

因此,您的
组合
将如下所示:

compose :: a -> [(a -> a)] -> a
compose x0 fs = foldl (??) x0 fs
compose :: a -> [(a -> a)] -> a
compose x0 fs = foldl g x0 fs
    where g xi f = ...
所以现在的问题是我们在
中做什么?
。第一个参数是累加器,第二个参数是列表的元素,一个函数。因此,我们必须实施以下措施:

compose :: a -> [(a -> a)] -> a
compose x0 fs = foldl (??) x0 fs
compose :: a -> [(a -> a)] -> a
compose x0 fs = foldl g x0 fs
    where g xi f = ...
因此,我们希望将
f
应用于
xi
,以获得下一个
xi
。换句话说:

compose :: a -> [(a -> a)] -> a
compose x0 fs = foldl g x0 fs
    where g xi f = f xi
如果我们想简化
g
函数,我们可以将其写成:

compose :: a -> [(a -> a)] -> a
compose x0 fs = foldl g x0 fs
    where g = flip ($)
并进一步完善:

compose :: a -> [(a -> a)] -> a
compose = foldl (flip ($))
然后产生:

Prelude> foldl (flip ($)) 1 [(+1)]
2
Prelude> foldl (flip ($)) 1 [(+1),(+1)]
3
Prelude> foldl (flip ($)) 1 [(+1),(+1),(/2)]
1.5
三个或更多元素 如果要将元素数量限制为三个或更多,我们可以使用模式匹配:

compose :: a -> [(a -> a)] -> a
compose x0 fs@(_:_:_:_) = foldl (flip ($)) x0 fs

虽然程序不应该在没有元素的列表上运行有点奇怪,但是有一个或两个元素。

只有两种情况,零函数或至少一个

compose x [] = x
compose x (f:fs) = compose (f x) fs

这可以通过使用翻转的组合运算符级联列表函数来实现

Prelude> foldr1 (flip (.)) [(+5),(/2),(*3)] $ 1
9.0

有一个条件:至少有3个函数(组合1[(+1),(+1)]不应该工作)。我如何控制它?正如@Willem Van Onsem指出的,你可以使用flip($)而不是(\a b->b a),你可能会发现它更干净。@LokiTheCreator要求它不能与较短的列表一起工作是很奇怪的。通常,在任务分配中,我们会发现诸如“它必须处理长度大于等于3的列表”之类的要求,而不是“它必须在长度列表上失败”