2017-11-18 71 views
3

我所谈论的一个例子是takeWhileHaskell中的“隐形”函数参数如何工作?

takeWhile :: (a -> Bool) -> [a] -> [a] 

用法示例

takeWhile (< 3) [1,2,3,4,1,2,3,4] == [1,2] 

从我可以告诉(< 3)成为(a < 3)其中a是要检查在列表中的当前项目。

这是如何在Haskell做,我会怎么能够移动其中a去,所以我可以做类似

takeWhile ((length a) < 4) ["aaa", "aaaaa"] 
+3

如果你正在寻找谷歌果汁:这种语法,你省略了符号中缀运算符的一个操作数,称为_section_。 '(<3)'表示'(\ x - > x <3)'和'(“abc”++)'表示'(\ x - >“abc”++ x)'。 –

回答

9

(< 3)被称为“部分”,仅适用于中缀操作符。这是编写缩写函数的语法糖。 (< 3)相当于\x -> x < 3(3 <)相当于\x -> 3 < x

因此,(< 3)是返回Bool的一个参数的函数。这正是takeWhile的期望。

随着length,你必须写在全面的功能:

takeWhile (\x -> length x < 4) ["aaa", "aaaaa"] 

或定义自己的功能,您可以咖喱:

shorterThan n x = length x < n 

takeWhile (shorterThan 4) ["aaa", "aaaaa"] 

如果你喜欢冒险,你可以写

takeWhile ((< 4) . length) ["aaa", "aaaaa"] 

或者可能是以更可读的方式

(??) = flip (.) 

takeWhile (length ?? (< 4)) ["aaa", "aaaaa"] 
+0

Haskell已经训练了我很多东西来阅读从右到左的函数组成,因此'''版本对我来说可读性较差。 – 4castle

+0

@ 4castle这是一个作文,但不要这样读。考虑到 ??作为变量的占位符。 “东西的长度小于四”。 –

3

有无处可去,你要记住,在Haskell每个功能currified,所以,想在(+)功能,可以做下,想在第一类型:

(+) :: Num a => a -> a -> a 

现在我可以做我的自定义Plusone精选,plusTwo等,如此之快得益于curryfication,因为

(+) :: Num a => a -> a -> a 

有 “隐paranthesis”,真的是这样的:

(+) :: Num a => a -> (a -> a) 

意思给我一个号码给你一个功能回来,所以:

plusOne :: Num a => a -> a 
plusOne = (+1) 

plusTwo :: Num a => a -> a 
plusTwo = (+2) 

你能看到什么?你给予它只是两个参数中的一个变换的(+)在一个新的功能,也会有相同的<>功能,您可以创建功能greaterThanTen是这样的:在你的takeWhile (< 3)例如

greaterThanTen :: (Num a, Ord a) => a -> a 
greaterThanTen = (>10) 

所以你(< 3)是功能“小于3”,如果你“读”所有的功能将是“拿n而小于3”

你可以在控制台通过询问类型:t命令

:t (< 3) 
(< 3) :: (Num a, Ord a) => a -> Bool 
+2

但请注意'(> 10)4'与'(>)10 4'完全不同。虽然currying/partial应用程序可以让我们修正第一个参数,但section的语法允许使用'(10 <)和'(10 <)' - 这不仅仅是在工作中起作用,它还接受编译器的特殊解析和处理。 – chi

+0

@chi非常感谢你,像你这样的专家,我每天都会学到新东西:),就像......昨天!如果我的记忆没有失败,非常感谢评论和时间 –

3

takeWhile的第一个参数是谓词;这是您的一元函数(< 3),当参数具有数值语义并且小于3时,这是正确的。这个选项适用于每个列表成员,当谓词首次不成立时,这个选项组成一个新列表并终止。已通过的元素组成结果列表。

你的例子几乎是正确的,你只能将它转换成谓词形式,即创建一个一元函数,当参数(字符串)的长度小于4时,这是真实的。这可以通过例如

(\a -> (length a) < 4) 

然后

takeWhile (\a -> (length a) < 4) ["aaa", "aaaaa"] 

应该做你的期望。

相关问题