为什么对于具有 2 个元素的元组,长度返回 1,而对于具有更多元素的元组,则返回错误? [英] Why does length return 1 for a tuple with 2 elements, and gives an error for a tuple with more elements?

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

问题描述

我正在使用Haskell Programming from First Principles"一书学习 Haskell,直到第 4 章结束, 基本数据类型",我遇到了一些让我困惑的事情.这本书提到了一个函数 length 并说它适用于 Listss.一切都很好,但是当我用各种 Tuple 尝试这个 length 函数时,我看到的让我很困惑:

首先来看length的类型:

:t 长度长度 :: 可折叠 t =>t a ->整数

好的,所以我在上面读到接受一个可折叠的,为了方便起见,我认为它是一个列表,并返回一个 Int,即列表中元素的数量."因此我的第一个困惑是:为什么以下工作完全有效:

长度 (1, 1)1

因为对我来说,好像我刚刚将一个包含两个元素的元组传递给 length,它返回 1.元组是一个列表吗?元组是可折叠的吗?当然,为什么要1?

现在我更进一步:

长度 (1, 1, 1)<互动>:6:1:没有 (Foldable ((,,) t0 t1)) 的实例源于长度"的使用表达式中:长度(1, 1, 1)在it"的等式中:it = length (1, 1, 1)<互动>:6:9:(Num t0) 没有由文字1"引起的实例类型变量t0"不明确注意:有几种可能的情况:instance Num Integer -- 在‘GHC.Num’中定义instance Num Double -- 在‘GHC.Float’中定义实例 Num Float -- 在GHC.Float"中定义...加上另外两个表达式中:1在'length'的第一个参数中,即'(1, 1, 1)'表达式中:长度(1, 1, 1)<互动>:6:12:(Num t1) 没有由文字1"引起的实例类型变量‘t1’不明确注意:有几种可能的情况:instance Num Integer -- 在‘GHC.Num’中定义instance Num Double -- 在‘GHC.Float’中定义实例 Num Float -- 在GHC.Float"中定义...加上另外两个表达式中:1在'length'的第一个参数中,即'(1, 1, 1)'表达式中:长度(1, 1, 1)

再试一次:

长度 (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 :: Int)

但以下有效:

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

对于我在上面观察到的行为有什么好的解释吗?我是否误读了 length 的类型?还是幕后有其他事情发生?

解决方案

您遇到了 Haskell cause célèbre 引发了很多讨论和咬牙切齿.

基本上,为了Foldable(提供length的类型类),二元组不被认为是两个元素的容器,而是一个一个元素的容器,伴随着一些上下文.>

您可以从任何 Foldable a 中提取 a 类型的元素列表.请注意,对于二元组,Foldable 的类型变量是元组的 第二个 元素的类型变量,它可以与第一个元素的类型不同.

如果你有一个 ('c',2) :: (Char,Int) 元组,你就不能提取两个 Int在那种情况下!但是当类型相同时,它会变得混乱.

至于为什么 length (1::Int, 1::Int, 1::Int) 失败,三元组没有定义 Foldable 实例,但也许他们应该有一个,以保持一致性.三元组的长度也为 1.

顺便说一下,Identity 函子,可以被认为是一种 1 元组,也是 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天全站免登陆