GHC имеет тип литерала уровня Nats. Я могу читать кое-что о них, например, здесь:Тип уровня Haskell буквальный Nat: статус?
https://ghc.haskell.org/trac/ghc/wiki/TypeNats
К сожалению, там, кажется, мало документации о них, и почти ничего, что я пытаюсь сделать с ними на самом деле работает.
Комментарий 18 из this page упоминает этот простой пример размера параметризованных ЗВТ (я добавил ЯЗЫКА прагмами и оператор импорта):
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Vec :: Nat -> * -> * where
Nil :: Vec 0 a
(:>) :: a -> Vec n a -> Vec (n+1) a
(+++) :: Vec n a -> Vec m a -> Vec (n+m) a
Nil +++ bs = bs
(a :> as) +++ bs = a :> (as +++ bs)
Он не работал в то время, но затем реализация была предположительно модифицированный так, чтобы это сработало. Это было 5 лет назад ... но это не работает на моем GHC 7.10.1:
trash.hs:15:20:
Could not deduce ((n + m) ~ ((n1 + m) + 1))
from the context (n ~ (n1 + 1))
bound by a pattern with constructor
:> :: forall a (n :: Nat). a -> Vec n a -> Vec (n + 1) a,
in an equation for ‘+++’
at trash.hs:15:2-8
NB: ‘+’ is a type function, and may not be injective
Expected type: Vec (n + m) a
Actual type: Vec ((n1 + m) + 1) a
Relevant bindings include
bs :: Vec m a (bound at trash.hs:15:15)
as :: Vec n1 a (bound at trash.hs:15:7)
(+++) :: Vec n a -> Vec m a -> Vec (n + m) a
(bound at trash.hs:14:1)
In the expression: a :> (as +++ bs)
In an equation for ‘+++’: (a :> as) +++ bs = a :> (as +++ bs)
В чем заключена сделка? Являются ли тип литературного уровня Натсом приемлемым для такого рода вещей? Если да, то каким образом я могу реализовать функцию (+++)? Если нет, то в чем их прецедент?
Я думаю, что этот _is_ решил окончательно работать в GHC-7.12 ... но в 7.10 вы можете как минимум [загрузить плагин] (https://hackage.haskell.org/package/ghc-typelits-natnormalise- 0.3), который должен сделать трюк. – leftaroundabout
Спасибо, что указали это. Но я вижу, что даже с этим плагином вы, по-видимому, все еще не можете обойтись без обхода системы типов. См. Использование unsafeCoerce в определении UNat [здесь] (https://github.com/clash-lang/ghc-typelits-natnormalise/blob/master/tests/Tests.hs). –
Да, это немного неловко. То, что я сделал до сих пор, вместо использования 'GHC.TypeLits', прикрепляется [к определенному вручную типу Peano] (https://github.com/leftaroundabout/manifolds/blob/08c5ffd4dd8b9a6053036a6bd4c0864cf23bffa6/manifolds/Data/CoNat. hs # L60), с классом типа типа codata, чтобы принимать схемы рекурсии и т. д. на уровень «Nat», а не явно решать любые равенства чисел. – leftaroundabout