Haskell中的函数合成
我有一个函数,它接受3个函数,并将它们组合起来改变一个列表参数 例如,一个测试用例调用是:chain init tail reverse“Haskell!”输出应该是lleksa 我尝试了几种不同的方法来解决这个问题,包括使用Haskell中的函数合成,haskell,Haskell,我有一个函数,它接受3个函数,并将它们组合起来改变一个列表参数 例如,一个测试用例调用是:chain init tail reverse“Haskell!”输出应该是lleksa 我尝试了几种不同的方法来解决这个问题,包括使用map函数,但我一直遇到关联问题。所以我做了 chain :: Ord a => [a] -> a chain f g h x = f.g.h$x 错误是无法匹配预期的类型[t0->t1->t2->a0] 当我直接在GHCi中输入问题时,比如写,init.ta
map
函数,但我一直遇到关联问题。所以我做了
chain :: Ord a => [a] -> a
chain f g h x = f.g.h$x
错误是无法匹配预期的类型[t0->t1->t2->a0]
当我直接在GHCi中输入问题时,比如写,init.tail.reverse$“Haskell!”
,它可以正常工作
有没有办法包含三个函数参数?我在示例中只看到了两个。当prelude分析您的函数时:
chain f g h x = f.g.h$x
它假定您正在接收函数f
、g
和h
。为什么会这样假设?因为
操作符的目的是链接函数。因此,如果您使用它,是因为您正在链接函数
您为函数([a]->a)
定义了一个类型签名,该签名与函数应该接收和返回的签名不同。一种解决方案是不指定类型签名并将其留待前奏,另一种是更正类型签名
但是,如果您希望函数接收a
列表并返回a
,则应将函数修改为以下内容:
chain :: (Ord a) => [a] -> a
chain (x:xs) = ...
当prelude分析您的功能时:
chain f g h x = f.g.h$x
它假定您正在接收函数f
、g
和h
。为什么会这样假设?因为
操作符的目的是链接函数。因此,如果您使用它,是因为您正在链接函数
您为函数([a]->a)
定义了一个类型签名,该签名与函数应该接收和返回的签名不同。一种解决方案是不指定类型签名并将其留待前奏,另一种是更正类型签名
但是,如果您希望函数接收a
列表并返回a
,则应将函数修改为以下内容:
chain :: (Ord a) => [a] -> a
chain (x:xs) = ...
对于由3个函数组成的高阶函数,最常见的类型签名是:
chain :: (b -> c) -> (b1 -> b) -> (a -> b1) -> a -> c
chain f g h x = f.g.h$x
(您也可以在不使用x
的情况下编写定义,只需
chain f g h = f.g.h
)。请注意,中间函数b
和b1
的返回类型是任意的,唯一的要求是它们必须与下一个函数的参数类型匹配。现在,如果您调用chain init tail reverse“Haskell!”
,您将得到“lleksa”
如果您知道如何编写函数,但不知道其正确的类型,可以让GHCi为您推断类型。只需在那里加载函数并键入例如:t chain
(:t
是:type
的缩写,请参阅)
您可以更进一步,由任意数量的函数组成。(但在这种情况下,类型系统会强制您少使用一些常规类型签名。) 此函数获取从
a
到a
的函数列表,并将它们组合在一起。如果列表为空,则只返回identity函数。使用chainN
可以编写如下内容
chainN [init, tail, reverse] "Haskell!"
对于由3个函数组成的高阶函数,最常见的类型签名是:
chain :: (b -> c) -> (b1 -> b) -> (a -> b1) -> a -> c
chain f g h x = f.g.h$x
(您也可以在不使用x
的情况下编写定义,只需
chain f g h = f.g.h
)。请注意,中间函数b
和b1
的返回类型是任意的,唯一的要求是它们必须与下一个函数的参数类型匹配。现在,如果您调用chain init tail reverse“Haskell!”
,您将得到“lleksa”
如果您知道如何编写函数,但不知道其正确的类型,可以让GHCi为您推断类型。只需在那里加载函数并键入例如:t chain
(:t
是:type
的缩写,请参阅)
您可以更进一步,由任意数量的函数组成。(但在这种情况下,类型系统会强制您少使用一些常规类型签名。) 此函数获取从
a
到a
的函数列表,并将它们组合在一起。如果列表为空,则只返回identity函数。使用chainN
可以编写如下内容
chainN [init, tail, reverse] "Haskell!"
有没有办法包含三个函数参数?我在示例中只看到了两个
你可能应该复习你读过的任何介绍性材料,或者尽可能地挑选一些介绍性材料。你似乎很困惑
当我直接在GHCi中输入问题时,比如写,init.tail.reverse$“Haskell!”
,它可以正常工作
您可以使用ghci
查找表达式的类型
λ:> chain f g h x = f.g.h$x
λ:> :t chain
chain :: (b1 -> c) -> (b2 -> b1) -> (a -> b2) -> a -> c
这只是一个专业化的
chain :: ([a] -> [a]) -> ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
我猜这就是你想写的
不管它值多少钱,如果你只是在列表上工作,你可能会想要下面这样的东西
chain :: [[a] -> [a]] -> [a] -> [a]
chain = foldr (.) id
启动GHCi:
λ:> chain = foldr (.) id
λ:> chain [init, tail, reverse] "Haskell!"
"lleksa"
你得到了我猜你想要的结果。如果您还不明白这是如何工作的,不要担心,坚持使用其他解决方案,并在您准备好时返回
有没有办法包含三个函数参数?我在示例中只看到了两个
你可能应该复习你读过的任何介绍性材料,或者尽可能地挑选一些介绍性材料。你似乎很困惑
当我直接在GHCi中输入问题时,比如写,init.tail.reverse$“Haskell!”
,它可以正常工作
您可以使用ghci
查找表达式的类型
λ:> chain f g h x = f.g.h$x
λ:> :t chain
chain :: (b1 -> c) -> (b2 -> b1) -> (a -> b2) -> a -> c
这只是一个专业化的
chain :: ([a] -> [a]) -> ([a] -> [a]) -> ([a] -> [a]) -> [a] -> [a]
我猜这就是你想写的
无论如何,你可能会