有没有一种方便的方法来使用单遍历构建更大类型级别的Peano数?

时间:2015-02-14 05:15:04

标签: haskell classy-prelude peano-numbers

单遍历软件包使用MinLen的类型级别Peano编号。我可以使用链式Succ s构建它们:

toMinLen [1,2,3] :: Maybe (MinLen (Succ (Succ Zero)) [Int])

但这很快就会失控:

toMinLen [1,2,3] :: Maybe (MinLen (Succ (Succ (Succ (Succ (Succ Zero))))) [Int])

有没有方便的方法来构建更大的Peano数字?我看到GHC有一个TypeLiterals扩展,但我不确定我是否可以在这里使用它。或者,我可以创建像:

这样的同义词
type One = Succ Zero
type Two = Succ One

等等;做某事已经存在于某个地方了?

3 个答案:

答案 0 :(得分:4)

TypeLits非常适合类型级数字。此外,它很容易只用于语法糖,并保持底层库特定的实现不变。

{-# LANGUAGE
  UndecidableInstances, TypeFamilies,
  DataKinds, TypeOperators #-}

import qualified GHC.TypeLits as TL

data Nat = Zero | Succ Nat

newtype MinLen (n :: Nat) a = MinLen a

我们必须定义一个将文字转换为数字类型的类型系列:

type family Lit (n :: TL.Nat) :: Nat where
  Lit 0 = Zero
  Lit n = Succ (Lit (n TL.- 1))

现在,只要您需要Lit n字面值,就可以使用Nat。在GHCi:

>:kind! MinLen (Lit 3)
MinLen (Lit 3) :: * -> *
= MinLen ('Succ ('Succ ('Succ 'Zero)))

答案 1 :(得分:2)

有一个包这类的东西:type-level。这有点令人生畏,我还没有真正探索过它。但是你不应该需要那么大的力量,所以你可以自己动手。

如果您愿意使用UndecidableInstances,事情就很容易了。大致相似的东西(我不确切知道该库中的自然界是如何定义的;如果它不使用DataKinds,您可能必须使用*种而不是Nat种类,您可能需要写'Succ'Zero而不是SuccZero - 我对此不太清楚方面):

{-# LANGUAGE UndecidableInstances, TypeFamilies, DataKinds, TypeOperators #-}

module TAR where

-- You wouldn't actually use this line, because the library
-- provides the naturals
data Nat = Zero | Succ Nat

-- Digits and Ten to get things started
type One = Succ Zero
type Two = Succ One
type Three = Succ Two
type Four = Succ Three
type Five = Succ Four
type Six = Succ Five
type Seven = Succ Six
type Eight = Succ Seven
type Nine = Succ Eight
type Ten = Succ Nine

type family Plus (a::Nat) (b::Nat) where
  Plus Zero n = n
  Plus (Succ m) n = Plus m (Succ n)

type family Times (a::Nat) (b::Nat) where
  Times Zero n = Zero
  Times (Succ m) n = Plus n (Times m n)

type Decimal (a::[Nat]) = Decimal' a Zero

type family Decimal' (a::[Nat]) (n::Nat) where
  Decimal' '[] n = n
  Decimal' (a ': bs) n = Decimal' bs (Plus a (Times Ten n))

然后你可以写点像

Decimal '[One, Two, Five]

表示125。

答案 2 :(得分:1)

您可以移植type-natural's QuasiQuoters