如何计算Haskell中元组的长度?

如何计算Haskell中元组的长度?,haskell,Haskell,我尝试在web和stackexchange中搜索,但令人惊讶的是,并没有人询问如何以下面的形式计算Haskell中元组的长度 假设在Haskell中有类似(1,2,3,4)或(1,3,5,6,7)的元组,并希望编写计算元组长度的长度函数。我该怎么做?对于列表,我知道如何使用递归而不显式调用内置函数。但元组是不同的,我不能用“头”-“尾”来区分 该方法是否需要创建新的数据类型?一个可能的答案(仅使用基本库)是 最近我在伦敦哈斯克尔就这个问题作了一次完整的演讲。幻灯片是,但视频还没有发布。在这方面你

我尝试在web和stackexchange中搜索,但令人惊讶的是,并没有人询问如何以下面的形式计算Haskell中元组的长度

假设在Haskell中有类似(1,2,3,4)或(1,3,5,6,7)的元组,并希望编写计算元组长度的长度函数。我该怎么做?对于列表,我知道如何使用递归而不显式调用内置函数。但元组是不同的,我不能用“头”-“尾”来区分

该方法是否需要创建新的数据类型?

一个可能的答案(仅使用基本库)是


最近我在伦敦哈斯克尔就这个问题作了一次完整的演讲。幻灯片是,但视频还没有发布。

在这方面你找不到任何东西的原因是,计算元组的长度没有多大意义:

  • 它是预先确定的编译时间(也就是说,您不妨对它进行硬编码)
  • 对于这些信息,您实际上做不了什么:与列表不同,在通用元组中不可能为特定条目编制索引
也就是说,可以实现您的目标,但是这不应该是一个普通函数,而是一个类型级别的函数,也称为类型族。使用NAT类型:

{-# LANGUAGE TypeFamilies, DataKinds #-}
import Data.Singletons
import Data.Singletons.TypeLits

type family TupLength a :: Nat where
  TupLength () = 0
  TupLength (a,b) = 2
  TupLength (a,b,c) = 3
  TupLength (a,b,c,d) = 4
  -- ...
  TupLength x = 1
然后


这样一个函数的类型是什么?这就是问这个问题的重点。我看不出这怎么可能。不同长度的元组不会共享同一类型,我不知道如何利用创建新数据类型来支持长度函数。出于好奇,您为什么要这样做?元组的长度在编译时是固定的,因此不需要“计算”任何内容。您可以使用类型类,如
class TupLen a where TupLen::a->Int
实例TupLen(a,b)where TupLen=2
,&c,但这并不是非常有用。值得注意的是,这不仅会为元组提供“长度信息”,还会为所有其他类型的数据结构提供“长度信息”,可能并不总是预期的结果。
{-# LANGUAGE TypeFamilies, DataKinds #-}
import Data.Singletons
import Data.Singletons.TypeLits

type family TupLength a :: Nat where
  TupLength () = 0
  TupLength (a,b) = 2
  TupLength (a,b,c) = 3
  TupLength (a,b,c,d) = 4
  -- ...
  TupLength x = 1
> mapM_ print [ natVal (sing :: SNat (TupLength ()))
              , natVal (sing :: SNat (TupLength (Int,String,Double)))
              , natVal (sing :: SNat (TupLength Bool)) ]
0
3
1