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

时间:2017-06-06 21:13:07

标签: haskell

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

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

该方法是否涉及创建新数据类型?

2 个答案:

答案 0 :(得分:7)

你没有找到任何相关内容的原因是计算元组的长度没有多大意义:

  • 这是预先确定的编译时间(即你也可以硬编码)
  • 你可以用这些信息做很多事情:与例如列表中,索引通用元组中的特定条目是不可能的。

那说,有可能实现你的目标,但这不应该是正常的功能,而是类型级功能,也就是类型系列。使用singleton类型nats:

{-# 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

答案 1 :(得分:5)

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

import Data.Data
import Data.Functor.Const

length :: Data a => a -> Int
length =
  getConst .
  gfoldl (\(Const c) _ -> Const (c+1)) (const 0)

我最近在伦敦哈斯克尔就这个问题进行了全面的讨论。幻灯片是here,但视频尚未发布。