Полезным подходом является нефункционализация.Вы можете реализовать его самостоятельно или найти реализацию в библиотеке singletons
.
Ядро является «открытым видом»:
data TYFUN :: Type -> Type -> Type
type TyFun a b = TYFUN a b -> Type
TyFun a b
- открытый вид;он не закрыт как нормальный, продвинутый, data
вид.Вы «объявляете» новые функции следующим образом.
data Plus :: TyFun Nat (TyFun Nat Nat)
Затем вы можете определить это семейство типов, чтобы связать объявление и определение
type family Apply (f :: TyFun a b) (x :: a) :: b
data PlusSym1 :: Nat -> TyFun Nat Nat -- see how we curry
type instance Apply Plus x = PlusSym1 x
type instance Apply (PlusSym1 x) y = x + y
Теперь, Plus
- это обычный конструктор типов:тип данных, а не семейство типов.Это означает, что вам разрешено передавать его другим типам семей.Обратите внимание, что они должны быть TyFun
осознающими себя.
type family Foldr (cons :: TyFun a (TyFun b b)) (nil :: b) (xs :: [a]) :: b where
Foldr _ n '[] = n
Foldr c n (x:xs) = Apply (Apply c x) (Foldr c n xs)
type Example = Foldr Plus 0 [1,2,3]
Идея открытого вида заключается в том, что Type
уже является открытым видом, а такие виды, как A -> Type
, A -> B -> Type
, сами открыты.,TYFUN
- это тег, идентифицирующий вещи как TyFun
s, а TyFun
- это открытый вид, который эффективно не пересекается с другими открытыми типами.Вы также можете использовать Type
открытый вид прямой:
type family TyFunI :: Type -> Type
type family TyFunO :: Type -> Type
type family Apply (f :: Type) (x :: TyFunI f) :: TyFunO f
data Plus :: Type
data PlusSym1 :: Nat -> Type
type instance TyFunI Plus = Nat
type instance TyFunO Plus = Type
type instance TyFunI (PlusSym1 _) = Nat
type instance TyFunO (PlusSym1 _) = Nat
type instance Apply Plus x = PlusSym1 x
type instance Apply (PlusSym1 x) y = x + y
С положительной стороны, это может обрабатывать функции зависимого типа, но, с другой стороны, это происходит только потому, что он бесстыдно выбрасываетпроверяя все «Type
ly-typed».Это не так плохо, как String
код с типичной линией, так как это все время компиляции, но все же.