Haskell类型长度+ 1

Xia*_*ang 7 haskell

任何人都可以帮我解释长度+ 1的类型我尝试用以下命令输入ghci :t length + 1 它返回Num([a]->Int)=>[a]->Int 这是什么意思?谢谢

bhe*_*ilr 9

看看的类型+:

> :t (+)
(+) :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

因此,两个参数必须来自同一个实例Num,并返回其中一个.然后看看类型length:

> :t length
length :: [b] -> Int
Run Code Online (Sandbox Code Playgroud)

(注意我已经改为在b这里用作类型变量,但它没有改变含义).

所以,如果你有length + something,那么length必须有一个实现的类型Num.由于length已经将类型设置为[b] -> Int,这意味着[b] -> Int需要是一个实例Num,并且something必须具有相同的类型.由于Haskell中的数字文字是多态的,这意味着1可以只具有类型Num a => a,并且可以通过上下文选择精确的实例.因为在表达式中length + 1,两个参数+必须具有相同的类型,这意味着必须1具有相同的类型,这意味着length如果我们明确地写出所有类型,我们就会有类似的东西.

((+) :: Num ([b] -> Int) => ([b] -> Int) -> ([b] -> Int) -> ([b] -> Int))
    (length :: [b] -> Int)
    (1      :: [b] -> Int)
Run Code Online (Sandbox Code Playgroud)

(以前缀形式编写并分成多行,以便我们实际读取它).

基本上,这就是说,为了添加内容length,你必须首先定义Numfor length类型的实例.返回类型[b] -> Int只是说它返回的东西与它的类型相同length.

这有用吗?不,几乎可以肯定不是.这是Haskell类型系统的一个特性,你可以Num任何类型编写有趣和奇怪的实例,但这并不意味着Num每种类型的实例都是有用的,可以通过智能方式定义,甚至可以在不诉诸的情况下实现undefined.


我们可以Num为这种类型编写一个实例,但我会选择在一个内部编写它,newtype因为它可以让我们避免语言扩展.

newtype Silly a = Silly { unSilly :: [a] -> Int }

instance Num (Silly a) where
    fromInteger x = Silly $ const (fromInteger x)
    Silly f + Silly g = Silly $ \l -> f l + g l
    Silly f * Silly g = Silly $ \l -> f l * g l
    negate (Silly f) = Silly $ negate . f
    abs (Silly f) = Silly $ abs . f
    signum (Silly f) = Silly $ signum . f
Run Code Online (Sandbox Code Playgroud)

然后我们可以用它作为

> (unSilly $ Silly length + 1) [1, 2, 3]
4
> (unSilly $ Silly length * Silly length) [1, 2, 3, 4]
16
> (unSilly $ negate $ Silly length) [1, 2, 3]
-3
Run Code Online (Sandbox Code Playgroud)

但这并不是真的有用,它增加了相当多的样板来做相当于的事情

> length [1, 2, 3] + 1
4
> length [1, 2, 3, 4] * length [1, 2, 3, 4]
16
> negate $ length [1, 2, 3]
-3
Run Code Online (Sandbox Code Playgroud)

虽然在某些例子中有点酷:

> (unSilly $ Silly head + Silly last) [10, 0, 1, 2, 3, 4, 5]
15
Run Code Online (Sandbox Code Playgroud)

但这仅适用于类型列表[Int].

  • 非常感谢,它帮助我完全理解haskell类型.实际上,长度+ 1是(+)的表达式,那么长度需要限制为Num实例.我们把Num([a] - > Int)用来实现它.此外,我们还需要一个para和一个返回值,因此我们将[a] - > Int放在这里.对? (3认同)
  • @Bolo它有正确的种类,因为该类型不能再接受任何类型变量.它的工作原理是因为数字文字是多态的,而`fromInteger`就是这样做的.本质上,编译器在内部用文字"1"替换为"fromInteger 1".由于在定义`Num`时需要这样做,因此您始终可以将文字转换为您自己的自定义类型. (2认同)