目前我正在学习Haskell,但我正在努力学习一些例子的语法。他们究竟是什么意思?
首先:这两个lambdas(-> \y
和y
)有什么区别?
lambda1 = \x -> \y -> x + y
lambda2 = \x y -> x + y
第二:这是什么意思?这是一个充当“伪”列表生成器的lambda,它生成一个包含3个元素的列表。我该如何创建这样的列表?
lambda3 = [\x -> x+1, \x -> 2*x, \x -> x^2]
第三次:\_
究竟意味着什么?
lambda4 = \_ -> (\x -> x+1, \() -> 'a')
答案 0 :(得分:10)
lambda2
是lambda1
的语法糖。所有这些都是等价的:
f = \x -> \y -> x + y
f = \x y -> x + y
f x = \y -> x + y
f x y = x + y
f x y = (+) x y
f x = (+) x
f = (+)
lambda3
是数字上的一元函数列表。每个函数都有(Num a) => a -> a
类型,因此列表的类型为(Num a) => [a -> a]
。您可以使用map
或列表推导来生成一个值列表:
fs = [\x -> x+1, \x -> 2*x, \x -> x^2]
map (\f -> f 3) fs
map ($ 3) fs
[f 3 | f <- fs]
==
[4, 6, 9]
lambda4
使用模式匹配语法。例如,如果您有数据类型:
data Foo = Foo Int String
然后你可以编写一个模式匹配的lambda:
f = \ (Foo n s) -> concat (replicate n s)
f (Foo 3 "bar") == "barbarbar"
(但与case
不同,如果Foo
有多个构造函数,则无法提供替代模式。)
_
模式只是说“接受一个值而忽略它”,所以lambda4
是一个接受参数的函数,忽略它,并返回一对(2元组)的一元函数,类型(Num a) => a -> a
的第一个和() -> Char
类型的第二个,因此其类型为Num a => r -> (a -> a, () -> Char)
。
lambda4 = \_ -> (\x -> x+1, \() -> 'a')
lambda4 = \ignored -> (\x -> x+1, \() -> 'a')
(inc, getA) = lambda4 ()
inc 3 == 4
getA () == 'a'
忽略其参数的函数可以使用const
函数构造,而运算符部分((+ 1)
)通常优先于lambdas(\x -> x + 1
),因此您也可以编写以上内容为:
lambda4 = const ((+ 1), const 'a')
答案 1 :(得分:3)
首先:这两个lambdas之间有什么区别( - &gt; \ y和y)?
没有区别。两者都为同一输入产生相同的输出,并且由于它们是纯函数,因此可以确保它们不会产生您看不到的外部效果。
不同之处在于第一个lambda使用currying的语法糖。
var min = arr.SelectMany((subArr, i) => subArr.Select((value, j) => new { i, j, value }))
.OrderBy(x => x.value)
.First();
int firstIndex = min.i;
int secondIndex = min.j;
等于\x y -> x + y
。现在,你不觉得它看起来很像类型签名,比如\x -> \y -> x + y
吗? ;)
这意味着函数foo :: Int -> Int -> Int
需要2 foo
并生成Int
。
因为我对第二个问题没有一个非常准确的答案......
第三:
Int
究竟意味着什么?
这是与\_
变量关联的lambda函数(\
)。 _
用作占位符,表示“我不关心此变量的内容,我甚至会给它一个正确的名称”。
答案 2 :(得分:3)
关于第二个问题,lambda3
只是一个糟糕的变量名称。这是Num a => a -> a
类型的函数列表。您可以通过在ghci中键入以下内容来验证:
:t [\x -> x+1, \x -> 2*x, \x -> x^2]
答案 3 :(得分:0)
没有-> y
。阅读本文的正确方法是
(\ x -> (\ y -> (x + y)))
碰巧,Haskell有#34; curried函数&#34;,这意味着
\ x y -> (x + y)
恰好与上述相同。
lambda3
是一个包含三个元素的列表。这些元素中的每一个都恰好是一个功能。函数是Haskell中的数据;你可以将它们作为参数传递,将它们作为结果返回,将它们填入列表等等。
lambda3 = [ (\x -> x+1) , (\x -> 2*x) , (\x -> x^2) ]
lambda4 = \_ -> (\x -> x+1, \() -> 'a')
&#34; _
&#34;性格基本上意味着&#34;我不在乎这是什么;忽略它&#34;。您可以在任何可以使用模式的地方使用它。例如,
foobar x _ z = x + y
是一个3参数函数,完全忽略参数#2。阅读模式匹配,这应该变得清晰。 (即,它不与lambdas有关,它与模式有关。)