Ich untersuche die Typ-Familie Features von Haskell, und geben Sie Level-Berechnung. Es scheint, es ist ganz einfach, parametrischen Polymorphismus bei dem Art-Level zu erreichen mit PolyKinds
:So erstellen Sie eine "Art-Klasse" in Haskell oder Ad-hoc-Polymorphismus auf der Ebene der Typ-Typen
{-# LANGUAGE DataKinds, TypeFamilies, KindSignatures, GADTs, TypeOperators, UndecidableInstances, PolyKinds, MultiParamTypeClasses, FlexibleInstances #-}
data NatK = Z | S NatK
data IntK = I NatK NatK
infix 6 +
type family (x :: NatK) + (y :: NatK) :: NatK where
Z + y = y
(S x) + y = S (x + y)
-- here's a parametrically polymorphic (==) at the type-level
-- it also deals specifically with the I type of kind IntK
infix 4 ==
type family (a :: k) == (b :: k) :: Bool where
(I a1 a2) == (I b1 b2) = (a1 + b2) == (a2 + b1)
a == a = True
a == b = False
ich Dinge wie :kind! Bool == Bool
oder :kind! Int == Int
oder :kind! Z == Z
und :kind! (I Z (S Z)) == (I (S Z) (S (S Z)))
tun können.
Allerdings möchte ich type +
ad-hoc polymorph machen. Damit ist es auf die Instanzen beschränkt, die ich ihm gebe. Die 2 Instanzen hier wären Typen der Art NatK
und Typen der Art IntK
.
Ich versuchte zunächst, es parametrisch polymorphen machen:
infix 6 :+
type family (x :: k) :+ (y :: k) :: k where
Z :+ y = y
(S x) :+ y = S (x :+ y)
(I x1 x2) :+ (I y1 y2) = I (x1 :+ y1) (x2 :+ y2)
Dies funktioniert, wie ich :kind! (I (S Z) Z) :+ (I (S Z) Z)
tun können.
Allerdings kann ich auch :kind! Bool :+ Bool
tun. Und das macht keinen Sinn, aber es erlaubt es als einfacher Typ Konstruktor. Ich möchte eine Typfamilie erstellen, die solche fehlerhaften Typen nicht zulässt.
An diesem Punkt bin ich verloren. Ich habe Klassen mit einem type
Parameter versucht. Aber das hat nicht funktioniert.
class NumK (a :: k) (b :: k) where
type Add a b :: k
instance NumK (Z :: NatK) (b :: NatK) where
type Add Z b = b
instance NumK (S a :: NatK) (b :: NatK) where
type Add (S a) b = S (Add a b)
instance NumK (I a1 a2 :: IntK) (I b1 b2 :: IntK) where
type Add (I a1 a2) (I b1 b2) = I (Add a1 b1) (Add a2 b2)
Es erlaubt immer noch :kind! Add Bool Bool
.
Hat dies etwas mit der ConstraintKinds
Erweiterung zu tun, wo ich die :+
oder Add
auf einige "Art-Klasse" beschränken müssen?
Dank! Das ist ziemlich cool, aber könntest du darüber hinausgehen, was genau funktioniert? Das heißt, warum funktioniert es? Für Ihre Open + Closed-Lösung, KProxy-Lösung und die TypeInType-Lösung. – CMCDragonkai
Oh, aber ich habe gerade deine erste Lösung getestet, und es erlaubt immer noch ': Art! Fügen Sie Bool Bool hinzu, was zu 'Add Bool Bool :: *' führt. Ich hatte gehofft, dass dies ein Typfehler wird, anstatt akzeptiert zu werden !? – CMCDragonkai
Auch Ihre zweite Lösung ermöglicht 'Add Bool Bool'. Es wird nicht als ein Typfehler angezeigt. – CMCDragonkai