我目前正在从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
正在擦除类型信息吗?
答案 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)
这是因为t
和0
不同-t
是通用的,不存在。令人反感的行是:
fromInt :: Int -> IntNat t
fromInt 0 = 0 :: IntNat 0
forall t. t == 0
很难证明