为什么对于具有 2 个元素的元组,长度返回 1,而对于具有更多元素的元组,则返回错误? [英] Why does length return 1 for a tuple with 2 elements, and gives an error for a tuple with more elements?
问题描述
我正在使用Haskell Programming from First Principles"一书学习 Haskell,直到第 4 章结束, 基本数据类型",我遇到了一些让我困惑的事情.这本书提到了一个函数 length
并说它适用于 Lists
s.一切都很好,但是当我用各种 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 Lists
s. Everything is fine with that, but when I try this length
function with various Tuple
s, 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 Int
s 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屋!