Haskell类型长度+ 1 [英] Haskell type length + 1

查看:119
本文介绍了Haskell类型长度+ 1的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

查看 + 的类型:

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

所以这两个参数必须来自同一个 Num ,并返回其中之一。然后看看长度类型:

 > :t长度
长度:: [b] - > Int

(请注意,我已更改为使用 b b

所以如果你有 length + something ,那么 length 必须有一个实现 Num 的类型。由于长度的类型已被设置为 [b] - > Int ,这意味着 [b] - > Int 需要是 Num 的一个实例,而 something 必须具有相同的类型。由于Haskell中的数字文字是多态的,这意味着 1 可以具有类型 Num a =>一个,精确的实例可以通过上下文选择。由于在表达式 length + 1 中, + 的参数必须具有相同的类型,这意味着 1 必须具有与长度相同的类型,这意味着如果我们明确写出所有类型,就会有类似((+):: Num([b] - > Int)=>([b] - > (长度:: [b] - > Int)
(1:Int) - >([b]→> Int) :[b] - > Int)

(以前缀形式书写并分割成多行,实际上可以读它)。

所以基本上,这是说为了添加一些东西到长度 ,你必须先为长度的类型定义一个 Num 的实例。返回类型 [b] - > Int 只是说它返回的东西类型与 length



这有用吗?不,几乎肯定不是。这是Haskell类型系统的一个特性,您可以 类型编写 Num 的有趣和奇怪的实例。这并不意味着每种类型的 Num 的实例都是有用的,可以用智能的方式定义,甚至可以不使用 undefined
$ hr

我们可以为 Num 为这种类型,但我会选择将它写入 newtype 中,因为它可以避免语言扩展。

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

实例数(傻傻的a)其中
来自整数x =傻傻的$ const(来自整数x)
傻傻的f +傻傻的g =愚蠢的$ \\ \\ - l - > f l + g l
傻f *傻g =傻$ $ \\ - 1 - > f l * g l
negate(傻瓜f)=傻瓜$ negate。 f
abs(傻瓜f)=傻$ abs。 f
signum(傻傻的f)=愚蠢的$ signum。 f

然后我们可以使用它作为

 > (不合理$傻傻的长度+ 1)[1,2,3] 
4
> (不舒服$傻的长度*愚蠢的长度)[1,2,3,4]
16
> ($ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $但这并不是很有用,它增加了很多样板,可以做一些相当于 $ b

 >的东西。长度[1,2,3] + 1 
4
>长度[1,2,3,4] *长度[1,2,3,4]
16
>否定$ length [1,2,3]
-3

尽管在一些例子中很酷:

 > (不舒服的傻傻的头+愚蠢的最后)[10,0,1,2,3,4,5] 
15

但这只适用于 [Int] 类型的列表。


Could anyone help me to explain the type of length + 1 I tried to type into ghci with following command :t length + 1 it returns Num([a]->Int)=>[a]->Int what does this mean? Thx

解决方案

Look at the type of +:

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

So both arguments have to be from the same instance of Num, and it returns one of those. Then look at the type of length:

> :t length
length :: [b] -> Int

(Note that I've changed to use b here as the type variable, but it doesn't change the meaning).

So if you have length + something, then length must have a type that implements Num. Since length's type is already set as [b] -> Int, this means that [b] -> Int needs to be an instance of Num, and something would have to have the same type. Since numeric literals in Haskell are polymorphic, this means that 1 can just has the type Num a => a, and the precise instance can be chosen by context. Since in the expression length + 1, both arguments to + have to have the same type, this means that 1 has to have the same type as length, meaning that if we wrote out all the types explicitly we'd have something like

((+) :: Num ([b] -> Int) => ([b] -> Int) -> ([b] -> Int) -> ([b] -> Int))
    (length :: [b] -> Int)
    (1      :: [b] -> Int)

(Written in prefix form and split onto multiple lines so we can actually read it).

So basically, what this is saying is that in order to add something to length, you have to first define an instance of Num for length's type. The return type of [b] -> Int is just saying that it's returning something of the same type as length.

Is this useful? No, almost certainly not. It's a feature of Haskell's type system that you can write interesting and strange instances of Num for literally any type, but that does not mean that an instance of Num for every type is useful, definable in an intelligent way, or even possible without resorting to undefined.


We could write an instance for Num for this type, but I'll choose to write it inside a newtype because it lets us avoid language extensions.

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

Then we can use it as

> (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

But this isn't really useful, it adds quite a bit of boilerplate to do something equivalent to

> length [1, 2, 3] + 1
4
> length [1, 2, 3, 4] * length [1, 2, 3, 4]
16
> negate $ length [1, 2, 3]
-3

Although in some examples are kind of cool:

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

But this only works on lists of type [Int].

这篇关于Haskell类型长度+ 1的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆