length (1,2)
Run Code Online (Sandbox Code Playgroud)
返回结果,但是
length (1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
给出错误.这是为什么?
读类型的(,)和(,,)没有帮助.
编辑:我想的是长度 Data.Foldable length :: Foldable t => t a -> Int
这对Functor,Traversable尤其是Foldable对的情况有些争议.在某些情况下,它们允许代码编译并执行非预期的操作.我建议为三元组等添加缺少的仿函数实例,并且正如随后的线程所示,这真的触动了一个神经.那么,为什么不(,,)有一个Foldable实例?因为社区尚未就此达成共识.
这是FTP (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’
...
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
您没有看到可折叠或可遍历的实例,这就是为什么length没有为这些值定义的原因.
更新
因此(a,b)被认为是单值的容器b.
你可以通过观察这段代码的输出来看到这个:
import Data.Foldable (fold)
import Data.Monod
foo :: Sum Int
foo = fold (3,4) :: Sum Int
Run Code Online (Sandbox Code Playgroud)
评估foo回报Sum {getSum = 4}.