为什么Haskell类型的签名声明有多个箭头?

Bre*_*hio 17 syntax haskell types

对不起,措辞很差,但很难描述.

我想我会跳到这个例子:

add                     :: Integer -> Integer -> Integer
add x y                 =  x + y
Run Code Online (Sandbox Code Playgroud)

为什么:

:: Integer -> Integer -> Integer
Run Code Online (Sandbox Code Playgroud)

代替:

:: Integer, Integer -> Integer
Run Code Online (Sandbox Code Playgroud)

箭头是" 函数类型映射运算符 ",而不是某种分隔符,不是吗?

Die*_*lan 21

因为讨好.想想这个的类型:

add 3 :: Integer -> Integer
Run Code Online (Sandbox Code Playgroud)

如果给出add一个数字,则返回一个映射Integer到另一个整数的函数.所以你可以这样做:

map (add 3) [1..10]
Run Code Online (Sandbox Code Playgroud)

以与部分应用的返回类型不同的方式处理参数是没有意义的.

编辑澄清

我认为bheklilr很清楚类型签名可以像这样读取

add :: Integer -> (Integer -> Integer)
Run Code Online (Sandbox Code Playgroud)

我们可以使用更多参数的函数,zipWith3因为它是我能想到的唯一一个.

zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
Run Code Online (Sandbox Code Playgroud)

如果我们只是读取它的作用,它需要一个函数,它接受3个值并返回第四个然后分别列出这些值,并返回第四个值的列表.尝试一下.

add3 :: Int -> Int -> Int -> Int
add3 a b c = a + b + c

Prelude>zipWith3 add3 [1] [2] [3]
[6]
Run Code Online (Sandbox Code Playgroud)

虽然,在这种情况下,所有值都是类型,Int但它仍然证明了这一点.

现在如果我们不给它所有列表怎么办?如果我们给它只是没有列出add3.

zipWith3 add3 :: [Int] -> [Int] -> [Int] -> [Int]
zipWith3 add3 :: [Int] -> ([Int] -> [Int] -> [Int])
zipWith3 add3 :: [Int] -> [Int] -> ([Int] -> [Int])
Run Code Online (Sandbox Code Playgroud)

所以,现在我们有一个函数,它接受3个列表并返回一个列表.但这也是一个函数,它接受一个列表返回一个带有2个列表并返回一个列表的函数.真的没有办法区分它们.

(zipWith3 add3) [1,2] [3,4] [5,6] :: [Int]
(zipWith3 add3) [1,2] :: [Int] -> [Int] -> [Int]
Run Code Online (Sandbox Code Playgroud)

看看我要去哪里?参数之间没有区别是返回类型.

  • 我学习Haskell时非常头晕,实际上并不是一样的.我只有2天了,所以谢谢你容忍新秀问题:) (5认同)

lef*_*out 16

当我意识到这一点时,我的"啊哈"时刻

map :: (a -> b) -> [a] -> [b]
Run Code Online (Sandbox Code Playgroud)

当您明确分组时,实际上看起来更自然:

map :: ( a -> b )
    -> ([a]->[b])
Run Code Online (Sandbox Code Playgroud)

需要一个函数并返回一个列表函数.如果定义不明确,这种分组不太有效,是吗?

map :: ( a -> b
       ,[a])->[b]
Run Code Online (Sandbox Code Playgroud)

然而,这种分组在某种程度上是一种更"深入",更有用的思考功能的方式.特别是,如果你概括它:

class Functor f where
  fmap :: (a->b) -> f a->f b
Run Code Online (Sandbox Code Playgroud)

算符做两两件事:需要一些类型(如ab),并将其关联到另一种类型的(f a,f b).但它也需要一个态射(a -> b)并将其与另一个态射(f a -> f b)联系起来.


bhe*_*ilr 7

类型签名更适合读取

add :: Integer -> (Integer -> Integer)
Run Code Online (Sandbox Code Playgroud)

这是非常不同的

add :: (Integer -> Integer) -> Integer
Run Code Online (Sandbox Code Playgroud)

第一个是表示一个函数,它接受Integer并返回一个新函数,该函数接受Integer并返回一个Integer.这是为了方便部分应用功能,所以像

(+) :: Int -> Int -> Int  -- specialized to Int

(1 +) :: Int -> Int

> map (1 +) [1..10]
[2,3,4,5,6,7,8,9,10,11]
Run Code Online (Sandbox Code Playgroud)