我很难理解这种类型声明是如何工作的。
类型为:(a -> b) -> (b -> c) -> (c -> d) -> a -> d
所以,对我来说,我把它解释为一个函数,它接受一个函数,该函数接受另一个输出值d的函数。
所以,这就是我的功能:
Example :: (a -> b) -> (b -> c) -> (c -> d) -> a -> d
Example f g h x = f ( g ( h (x) )
如果你们能帮助我澄清,我真的很感激。谢谢!
答案 0 :(得分:1)
我认为你已经知道你所写的类型背后的理论,所以我会尝试用一些直观的方式来阅读它(至少我希望如此,你的问题对我来说并不完全清楚)。< / p>
当你在类型中读到类似(a - &gt; b)的内容时,就像你说的那样,这是一个函数。例如(Int - &gt; Bool)是一个函数。
我们举个例子:
even :: Int -> Bool -- A more generic version of that is in the Prelude
even n = n `rem` 2 == 0
filter :: (Int -> Bool) -> [Int] -> [Int] -- And of that, too
filter _ [] = []
filter f (x:xs)
| f x = x : filter f xs
| otherwise = filter f xs
filteredEven :: [Int]
filteredEven = filter even [1..5] -- it gives [2, 4]
在这个例子中,我们有一个“高阶函数”,一个获取另一个函数并以某种方式使用它的函数。
在您定义的函数中,您只需使用3个函数(和另一个参数)。但你可以知道更多。
您在类型中声明的每个函数都接受从前一个函数返回的值。因此,可能的解决方案是您已经展示的解决方案。但这些类型是通用的。没有一个总函数返回一个通用值(其中total表示它终止总是返回一个不同于bottom的值,如果所有值都是total并且底部不同,那么它不会崩溃或返回undefined,例如)。因此,如果你想要一个完整的函数,你必须有一种方法来生成所请求的变量,从函数的上下文(它们的参数)。
在之前的示例中,使用您使用的名称,您必须返回类型d的值。您只能生成该类型的值,即h函数。但要使用h函数,您必须获得类型c的值。你只有g功能。但是你需要一个c类型的值。幸运的是,你有函数f,交换类型a的值会返回所需的值。我们有这个值(并且没有任何其他方法来获取该类型的值),因此可以编写该函数。我们不能以任何方式改变获得的值(多次调用函数不起作用,纯度和事实我们只有一种方法来产生值),所以这是构造函数的唯一方法,如果我们希望它是完全的:
Example (a -> b) -> (b -> c) -> (c -> d) -> a -> d
Example f g h x = h (g (f x)))
我们可以用许多其他方式编写函数,但它们给出的结果将始终相同(如果示例,f,g和h是总和而x不是底部)。所以类型可以很好地表达函数,因为我们可以理解函数如何工作只看类型!