为什么你不能得到(,,)的长度?

时间:2016-05-22 17:34:57

标签: haskell

length (1,2) 

返回结果,但

length (1, 2, 3)

给出错误。那是为什么?

阅读(,)(,,)的类型没有帮助。

编辑:我正在考虑来自Data.Foldable length :: Foldable t => t a -> Int的长度

3 个答案:

答案 0 :(得分:7)

FunctorTraversable以及最特别的Foldable个实例存在争议。在某些情况下,它们允许代码编译并执行非预期的操作。我proposed adding the missing functor instances for triples, etc.,正如随后的线索所示,这真的触动了一个神经。那么为什么没有(,,)Foldable个实例?因为社区尚未就此达成共识。

答案 1 :(得分:6)

这是FTP (Foldable-Traversable in Prelude)提案的结果。

有了这个,length现在被定义为任何可折叠的东西,并且事实证明对是有一个可折叠的实例:

ghci> :i (,)
data (,) a b = (,) a b  -- Defined in ‘GHC.Tuple’
...
instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
instance Foldable ((,) a) -- Defined in ‘Data.Foldable’
instance Traversable ((,) a) -- Defined in ‘Data.Traversable’
...

length (a,b)将始终返回1.

没有为高阶元组定义可折叠实例。例如,如果检查为三元组定义的类:

ghci> :i (,,)
data (,,) a b c = (,,) a b c    -- Defined in ‘GHC.Tuple’
instance (Bounded a, Bounded b, Bounded c) => Bounded (a, b, c)
instance (Eq a, Eq b, Eq c) => Eq (a, b, c)
instance (Ord a, Ord b, Ord c) => Ord (a, b, c)
instance (Read a, Read b, Read c) => Read (a, b, c)
instance (Show a, Show b, Show c) => Show (a, b, c)
instance (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c)

您没有看到可折叠或可遍历的实例,这就是为什么length没有为这些值定义的原因。

<强>更新

因此(a,b)被视为单个值b的容器。

您可以通过观察此代码的输出来看到这一点:

import Data.Foldable (fold)
import Data.Monod

foo :: Sum Int
foo = fold (3,4) :: Sum Int

评估foo会返回Sum {getSum = 4}

答案 2 :(得分:2)

简短的回答是,因为没有名为length的函数将(,,)作为输入。

有一个函数length以可折叠为输入:https://hackage.haskell.org/package/base-4.9.0.0/docs/Data-Foldable.html#v:length

如果你在ghci中输入:

:i (,)

您注意到它是可折叠的实例

(,,)

不是可折叠的实例。