为什么长度为2个元素的元组返回1,并为元组中的元素提供错误? [英] Why does length return 1 for a tuple with 2 elements, and gives an error for a tuple with more elements?

查看:153
本文介绍了为什么长度为2个元素的元组返回1,并为元组中的元素提供错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Haskell Programming from First Principles 一书来研究Haskell,并且在第4章结束时,基本数据类型,我遇到过让我困惑的东西。这本书提到了一个函数 length ,并表示它可以在 Lists s上运行。一切都很好,但当我尝试这个长度函数与各种 Tuple s,我看到困惑我:



首先,我们来看看长度的类型:

 :t长度
长度::可折叠t => t a - >诠释

好的,所以我在上面读取为需要折叠,我认为这是一个方便的列表,并返回一个Int,即列表中元素的数量。因此,我第一个困惑:为什么以下工作:

 长度(1,1)
1

因为对我来说,好像我刚刚传递了一个元组,其元素为 length ,它返回1.是元组列表吗?元组是否可折叠?当然,为什么 1



现在我再往前走一步:

  length(1, 1,1)

< interactive>:6:1:
由于使用'length '
在表达式中:length(1,1,1)
在'it'的等式中:it = length(1,1,1)

< interactive> ;:6:9:
没有从字面值'1'产生的实例(Num t0)
类型变量't0'不明确
注意:有几个潜在实例:
实例Num Integer - 定义于'GHC.Num'
实例Num Double - 定义于'GHC.Float'
实例Num Float - 定义于'GHC.Float'
...加两个
在表达式中:1
在'length'的第一个参数中,即'(1,1,1)'
在表达式中:length(1, 1,1)

<互动>:6:12:
由于字面值'1'
而没有实例(Num t1)类型变量't1'不明确
注意:有几个潜在的实例:
实例Num Integer - 在'GHC.Num'中定义
实例Num Double - 在'GHC中定义。 Float'
实例Num Float - 在'GHC.Float'中定义
...另外两个
在表达式中:1
在'length'的第一个参数中,即'(1,1,1)'
在表达式中:length(1,1,1)

另一个尝试:

  length(1 :: Int,1 :: Int,1 :: Int)

<互动>:7:1:
由于使用'长度'而没有(Foldable((,, ,, Int Int))
的实例
在表达式中:length(1 :: Int,1 :: Int,1 :: Int)
在'it'的等式中:it = length(1 :: Int,1 :: Int,1 ::诠释)

但是,以下工作:

 长度(1 :: Int,1 :: Int)
1

有没有对我在上面观察到的行为有很好的解释吗?我误读了长度的类型吗?还是幕后有其他事情?

解决方案

你碰到过一个Haskell 导致célèbre的问题,引发了很多讨论和咬牙切齿。 / p>

基本上,出于 Foldable (提供长度的类型类别),2元组不被视为容器两个元素,但是一个一个元素的容器伴随着一些上下文。



您可以提取 a 来自任何可折叠a 。请注意,对于2元组而言, Foldable 的类型变量是元组的第二个元素的类型变量,它可以不同于类型如果你有一个('c',2)::(Char,Int)元组,在这种情况下无法提取两个 Int s并不是个谜!但是,当类型相同时,它变得令人困惑。至于为什么长度(1 :: Int,1 :: Int,1 :: Int )失败,3元组没有定义的 Foldable 实例,但可能它们应该有一个,以保持一致性。 3元组的长度也为1。

顺便提一下, Identity functor,可以被认为是 Foldable ,当然也有长度为1的元素。



如果 Foldable 元组存在 ?我认为支持是的基本哲学是我们称之为丰满的一种。如果一个类型可以定义合法的方式成为一个类型类的实例,那么它应该有这个实例。即使它看起来不太有用,并且在某些情况下可能会令人困惑。

I'm studying Haskell using the book "Haskell Programming from First Principles", and towards the end of Chapter 4, "Basic datatypes", I've come across something that confused me. The book mentions a function length and says that it works on Listss. Everything is fine with that, but when I try this length function with various Tuples, what I see confused me:

First, let's see the type of length:

:t length
length :: Foldable t => t a -> Int

OK, so I read above as "takes a Foldable, which I think as a list for convenience, and returns an Int, that is the number of elements in the list." Hence my first confusion: Why does the the following work at all:

length (1, 1)
1

Because to me, it seems like I've just passed a tuple with two elements to length, and it returned 1. Is tuple a list? Is tuple Foldable? And of course, why 1?

Now I go one step further:

length (1, 1, 1)

<interactive>:6:1:
    No instance for (Foldable ((,,) t0 t1))
      arising from a use of ‘length’
    In the expression: length (1, 1, 1)
    In an equation for ‘it’: it = length (1, 1, 1)

<interactive>:6:9:
    No instance for (Num t0) arising from the literal ‘1’
    The type variable ‘t0’ is ambiguous
    Note: there are several potential instances:
      instance Num Integer -- Defined in ‘GHC.Num’
      instance Num Double -- Defined in ‘GHC.Float’
      instance Num Float -- Defined in ‘GHC.Float’
      ...plus two others
    In the expression: 1
    In the first argument of ‘length’, namely ‘(1, 1, 1)’
    In the expression: length (1, 1, 1)

<interactive>:6:12:
    No instance for (Num t1) arising from the literal ‘1’
    The type variable ‘t1’ is ambiguous
    Note: there are several potential instances:
      instance Num Integer -- Defined in ‘GHC.Num’
      instance Num Double -- Defined in ‘GHC.Float’
      instance Num Float -- Defined in ‘GHC.Float’
      ...plus two others
    In the expression: 1
    In the first argument of ‘length’, namely ‘(1, 1, 1)’
    In the expression: length (1, 1, 1)

Another try:

length (1::Int, 1::Int, 1::Int)

<interactive>:7:1:
    No instance for (Foldable ((,,) Int Int))
      arising from a use of ‘length’
    In the expression: length (1 :: Int, 1 :: Int, 1 :: Int)
    In an equation for ‘it’: it = length (1 :: Int, 1 :: Int, 1 :: Int)

But the following works:

length (1::Int, 1::Int)
1

Is there any good explanation for the behavior I'm observing above? Am I misreading the type of length? Or is there something else going on behind the scenes?

解决方案

You have encountered a Haskell cause célèbre that has sparked much discussion and gnashing of teeth.

Basically, for the purposes of Foldable (the typeclass that provides length), 2-tuples are not considered a container of two elements, but a container of one element accompanied by some context.

You can extract a list of elements of type a from any Foldable a. Notice that for 2-tuples the type variable of the Foldable is that of the second element of the tuple, and it can be different from the type of the first element.

If you had a ('c',2) :: (Char,Int) tuple, it would be no mystery that you couldn't extract two Ints in that case! But when the types are equal it becomes confusing.

As for why length (1::Int, 1::Int, 1::Int) fails, 3-tuples don't have a Foldable instance defined, but perhaps they should have one, for consistency. 3-tuples would also have length 1.

By the way, the Identity functor, that could be considered a kind of 1-tuple, is also Foldable and of course has length 1 as well.

Should the Foldable instance for tuples exist at all? I think the underlying philosophy in favor of yes is one of, shall we call it, "plenitude". If a type can be made an instance of a typeclass in a well defined, lawful way, it should have that instance. Even if it doesn't seem very useful and, in some cases, may be confusing.

这篇关于为什么长度为2个元素的元组返回1,并为元组中的元素提供错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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