2017-04-06 57 views
3

我试图理解下面的一段代码:即使参数丢失,为什么此功能仍能正常工作?

import Data.Char (ord) 

encodeInteger :: String -> Integer 
encodeInteger = read . concatMap ch 
    where ch c = show (ord c) 

但我不明白如何当encodeInteger被定义为需要一个字符串的函数这可以工作,但在第二行中,函数实现时没有该字符串参数。

此外,concatMap(根据hoogle)采用函数和列表,但仅提供功能ch

为什么此代码仍然有效?这个论证是不是神奇地通过了?它与咖喱有关吗?

编辑:为什么不就努力改变这样的:

encodeInteger :: String -> Integer 
encodeInteger a = read . concatMap ch a 
    where ch c = show (ord c) 
+1

函数'甲 - >乙 - >在Haskell C'表示功能'一个 - >(B - > C)',即,如果施加到一个'A'它产生一个'乙 - > C'。 'f a b'同样只是'(f a)b'。如此以来,'concatMap'是(简化的)'(一 - >并[b]) - >并[a] - >并[b]','concatMap ch'是一个函数'[A] - >并[b]'。 – Ryan

+0

嗨,谢谢,这无论如何都是有道理的。但是,我不应该做我在编辑下添加的内容吗? – user66875

+1

@ user66875您需要将整个构图应用于参数。现在,期待'concatMap ch a'成为一个函数('.'的第二个参数)。使用'阅读。 concatMap ch $ a' – Lazersmoke

回答

4

基本上定义一个函数

f = g 

相同定义函数

f x = g x 

在您的具体情况下,您可以使用

encodeInteger a = (read . concatMap ch) a 

来定义你的功能。需要的括号,否则它被解析为

encodeInteger a = (read) . (concatMap ch a) 

concatMap ch a不是一个函数,不能组成。最多你可以写

encodeInteger a = read (concatMap ch a) 
-- or 
encodeInteger a = read $ concatMap ch a 

关于“为什么concatMap ch只有一个参数?”。这是一个部分应用程序,在Haskell中很常见。如果你有

f x y z = x+y+z 

你可以叫f用更少的参数,并获得作为结果的剩余参数的函数。例如,f 1 2是取z并返回1+2+z的函数。

具体而言,感谢柯里里,没有这样的事情作为一个函数采取两个或更多的参数。每个函数总是只有一个参数。当你有一个像

foo :: Int -> Bool -> String 

一个函数,那么foo有一个参数,一个Int。它返回一个函数,它需要一个Bool并最终返回String。您可以通过编写

foo :: Int -> (Bool -> String) 

无论如何想象这一点,如果你看看钻营和部分应用程序,你会发现很多的例子。

3
encodeInteger :: String -> Integer 
encodeInteger = read.concatMap (\char -> show $ ord char) 

“=”的左侧(LHS)的encodeInteger是名称;它指的是“=”右侧的功能(RHS)。两者都具有功能类型:String -> Integer。两者都带有一个字符列表并产生一个整数。哈斯克尔使我们能够表达这样的功能,平等,而不指定形式参数(被称为point-free风格)。

现在,让我们来看看在RHS。 (。)运算符将两个函数组合在一起。所构成的函数以一个字符串作为从concatMap其输入,并产生出来的read作为组成函数的输出的整数。

concatMap本身需要2个输入,但是我们需要离开了第二个对于组成的函数,它需要一个字符串作为其输入。我们通过部分申请concatMap来实现这一目标,仅包括其第一个参数。