Können sagen wir folgendes haben:Einschränkende Instanzen
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilyDependencies #-}
type family CategoryLikeT p_a_b = t | t -> p_a_b
type IsCategoryLike p t a b = (t ~ CategoryLikeT (p, a, b))
class CategoryLike p where
(>>>) ::
(
IsCategoryLike p t1 a b,
IsCategoryLike p t2 b c,
IsCategoryLike p t3 a c
) => t1 -> t2 -> t3
Wir haben dann feststellen, dass diese kompiliert fein:
f ::
(
CategoryLike p,
IsCategoryLike p t1 a b,
IsCategoryLike p t2 b c,
IsCategoryLike p t3 c d,
IsCategoryLike p t4 a d
) => t1 -> t2 -> t3 -> t4
f x y z = x >>> y >>> z
Aber wir haben keine Instanzen noch definiert. Lets tun:
data BasicFunction
type instance CategoryLikeT (BasicFunction, a, b) = a -> b
instance CategoryLike BasicFunction where
(>>>) = flip (.)
Aber auch „Ints“ unter Zusatz Art Kategorie sind wie, wenn wir annehmen, nur „a“ und „b“ sind sowohl Void
, zum Beispiel: Daten BasicInt Typ-Instanz CategoryLikeT (BasicInt, Void, Void) = Int
instance CategoryLike BasicFunction where
(>>>) = (+)
natürlich ist die oben nicht funktioniert, weil es keine Einschränkungen ist auf „a“ oder „b“ in der Instanzdefinition, so gibt es keine Garantie >>>
bekommt alle gleich Typ, daher (+)
ist nicht allgemein genug. Also, was ich in Betracht gezogen wird wie folgt aktualisiert:
Erstens eine Einschränkungsart Zugabe:
type family CategoryConstraints p t a b
Und dann das Hinzufügen der Definition von IsCategoryLike
wie folgt aus:
type IsCategoryLike p t a b =
(t ~ CategoryLikeT (p, a, b), CategoryConstraints p t)
Wir können dann hinzufügen die folgende Einschränkung:
type instance CategoryConstraints BasicInt t = (t ~ Int)
Aber jetzt haben wir ein Problem. f
nicht mehr funktioniert, diesen Fehler geben:
Could not deduce: CategoryConstraints p (CategoryLikeT (p, a, c)))
Wir werden diese auf zwei Arten beheben:
Zum einen durch IsCategoryLike p t5 a c
den Zwängen in f
hinzufügen. Bei komplexeren Funktionen könnte dies jedoch sehr schnell unübersichtlich werden. Sie müssten für jede Operation eine Einschränkung hinzufügen. Auch geringfügige Änderungen wie das Ändern von (x >>> y) >>> z
zu x >>> (y >>> z)
erfordern eine Änderung der Signatur, die nicht erforderlich war, wenn die Einschränkungen nicht vorhanden waren.
Alternativ könnte die Typ-Signatur ganz weggelassen werden, oder Teil-Typ-Signaturen könnten verwendet werden.
Allerdings möchte ich vollständige Signaturen behalten, ohne dann zu wachsen und schwer zu warten. Können die Leute alternative Ansätze vorschlagen?
Die Schlüsselfrage ist, dass du 'f' mit einer Typ-Signatur schreiben kannst? – Clinton
@Clinton Immer noch keine großartige Signatur, aber ein bisschen besser. Zumindest kann es elegant mit sichtbaren Anwendungen verwendet werden – Alec