在Haskell中编写函数列表

在Haskell中编写函数列表,haskell,functional-programming,fold,function-composition,Haskell,Functional Programming,Fold,Function Composition,我需要定义一个函数来接收一个元组t1(String,(Int,Int,Int)和另一个元组t2(String,[(String,Int,[Fs]))。它必须返回元组t1,并在其第二个元素(Int,Int,Int)中修改值。这种改变是由存储在tuplet2中的函数引起的 如果我是正确的,首先我需要从第二个元组生成一个函数列表,这是我用fold做的: trd3 (a,b,c) = c listFunctions = foldr (++) [] (map trd3 (snd t2)) 当我想再次使用

我需要定义一个函数来接收一个元组t1
(String,(Int,Int,Int)
和另一个元组t2
(String,[(String,Int,[Fs]))
。它必须返回元组t1,并在其第二个元素
(Int,Int,Int)中修改值
。这种改变是由存储在tuplet2中的函数引起的

如果我是正确的,首先我需要从第二个元组生成一个函数列表,这是我用fold做的:

trd3 (a,b,c) = c
listFunctions = foldr (++) [] (map trd3 (snd t2))
当我想再次使用fold组合函数列表时,出现了一个问题,即它不起作用:

foldr (.) (snd t1) (foldr (++) [] (map trd3 (snd t2)))
举个例子,我可以这么说

t1 = ("Warrior",(15,5,12))
t2 = ("Bag",[("HP potion",5,[f1,f2]),("MP potion",3,[f3])])
f1 (a,b,c) = (a+10,b+5,c)
f2 (a,b,c) = (a+5,b+5,c)
f3 (a,b,c) = (a,b+5,c+15)
因此函数应该返回类似于
(f3.f2.f1)(15,5,12)

我也看到了这个链接:但无法100%理解它

如果有人能解释一下如何解决这个问题,我将不胜感激


非常感谢。

我不确定我是否完全理解了这个问题,但是您可以使用可折叠和
Endo
Monoid组合一个
a->a
(endofunctions)列表:

-- Given some listOfFunctions :: [a -> a] and initialValue :: a, for some type a:
appEndo (foldMap Endo listOfFunctions) initialValue
例如:

λ> import Data.Foldable (foldMap)
λ> import Data.Monoid
λ> appEndo (foldMap Endo [(+2), (*10), (/2)]) 50  -- This evaluates ((50/2)*10)+2
252.0

问题是您将
sndt1
放在哪里

foldr (.) (snd t1) (foldr (++) [] (map trd3 (snd t2)))
让我们先假设这个类型被检查过,然后它的计算结果是

f3 . f2 . f1 . snd t1
这是无稽之谈,因为
sndt1
不是一个函数,所以不能组合它

您要做的是首先组合函数,然后将结果函数应用于
sndt1
。您可以使用
id
作为
foldr
的第二个参数,即

foldr (.) id (foldr (++) [] (map trd3 (snd t2))) $ snd t1
评估结果是

f3 . f2 . f1 . id $ snd t1
这当然和

f3 . f2 . f1 $ snd t1

这正是您想要的。

您想要实现什么?如果您首先清楚地说明您想要实现什么,然后向我们展示您有问题的实现,我们可以更容易地帮助您。请在您的第二步中考虑合成函数的类型和基本情况。您正在使用
foldr(.)(snd t1)listFunctions
,它的计算结果不像您希望的那样是
(f3.f2.f1)(snd t1)
。它起作用了!您能解释一下
id
是什么以及您用
$snd t1
做了什么吗?非常感谢!@warty:
id
是身份函数,定义为
id x=x
,所以在某种意义上它是“不做任何事情”。
$
是一个进行函数应用的运算符,定义为
f$x=fx
。它的优先级非常低,因此经常使用它来代替括号。例如,
f3.f2.f1$sndt1
(f3.f2.f1)(sndt1)相同
。明白了,谢谢。正在检查,似乎正在反向创建合成(f1.f2.f3),首先应用f3,最后应用f1。我想我会在编写前反转列表。由于某些原因,foldr和foldl没有任何区别。还有一个疑问,为什么在foldr中使用4个参数而不是fold需要的3个参数?谢谢。@warty:前三个参数转到
foldr
。因为我们正在编写函数ns,
foldr
的结果是一个函数。该函数接收最终参数。函数应用程序关联到左侧,因此
(fx)y
fxy
相同,同样
(foldr fzxs)y
foldr fzxs
相同。