length (1,2)
返回结果,但
length (1, 2, 3)
给出错误。那是为什么?
阅读(,)
和(,,)
的类型没有帮助。
编辑:我正在考虑来自Data.Foldable
length :: Foldable t => t a -> Int
的长度
答案 0 :(得分:7)
对Functor
,Traversable
以及最特别的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 (,)
您注意到它是可折叠的实例
(,,)
不是可折叠的实例。