构造Nat类型

时间:2019-01-03 18:15:55

标签: haskell types

我目前正在从GHC.TypeLits中学习使用Nat

我试图通过以下定义将整数提升为类型级别以进行测试:

type IntNat (t::Nat) = Int

incNat :: IntNat t -> IntNat (t + 1)
incNat n = n + 1

fromInt :: Int -> IntNat t
fromInt(0) = (0 :: IntNat 0)
fromInt(n) = incNat (fromInt(n-1))

four = fromInt 4

据我了解,这应该导致:

four = 4 :: IntNat (Nat 4)

但是我得到了:

four = 4 :: IntNat t

我要去哪里了,只是fromInt正在擦除类型信息吗?

1 个答案:

答案 0 :(得分:2)

因为您定义了类型同义词,而不是新类型,所以其含义与您似乎想的完全不同。大致上,IntNat _将与Int并因此与任何其他IntNat _合并。

您可以通过定义其他实例并在列表中看到它们的统一性来进行尝试:

*Main> let five = 5 :: IntNat 99
*Main> let xs = [four, five] :: [IntNat 42]
*Main> :t xs
xs :: [IntNat 42]

或使用单个intnat:

*Main> let four' = four :: IntNat 1000
*Main> :t four'
four' :: IntNat 1000

请改为考虑使用新类型,例如newtype IntNat (n :: Nat) = IN Int。您会收到类似这样的错误:

• Couldn't match type ‘t’ with ‘0’
  ‘t’ is a rigid type variable bound by
    the type signature for:
      fromInt :: forall (t :: Nat). Int -> IntNat t
    at so.hs:12:1-26
  Expected type: IntNat t
    Actual type: IntNat 0
• In the expression: IN 0 :: IntNat 0
  In an equation for ‘fromInt’: fromInt 0 = IN 0 :: IntNat 0
• Relevant bindings include
    fromInt :: Int -> IntNat t (bound at so.hs:13:1)

这是因为t0不同-t是通用的,不存在。令人反感的行是:

fromInt :: Int -> IntNat t
fromInt 0 = 0 :: IntNat 0 

forall t. t == 0很难证明