Question

Toutes mes excuses à l'avance si cette question est un peu vague. Il est le résultat d'un rêve éveillé week-end.

Avec merveilleux système de type de Haskell, il est agréable d'exprimer délicieusement la structure mathématique (en particulier algébrique) comme classes de types. Je veux dire, jetez un oeil à numérique-prélude ! Mais en tirant parti de cette structure de type merveilleux dans la pratique a toujours semblé difficile à moi.

Vous avez une belle façon de type système d'expression qui v1 et v2 sont des éléments d'un V d'espace vectoriel et que w est un élément d'un espace vectoriel W. Le système de type vous permet d'écrire un programme en ajoutant v1 et v2, mais pas v1 et w. Génial! Mais en pratique, vous voudrez peut-être jouer avec potentiellement des centaines d'espaces vectoriels, et vous ne voulez certainement pas créer des types V1, V2, ..., V100 et les déclarer instances de la classe de types d'espace vectoriel! Ou peut-être vous lire des données du monde réel résultant des symboles a, b et c - vous pouvez exprimer que l'espace libre vectoriel sur ces symboles est vraiment un espace vectoriel

Vous êtes coincé, non? Pour faire beaucoup de choses que vous aimeriez faire avec des espaces vectoriels dans un cadre de calcul scientifique, vous devez renoncer à votre typesystem par ce qui précède une classe de types d'espace vectoriel et ayant des fonctions faire des vérifications de compatibilité temps courir à la place. Si vous devez? Devrait-il pas possible d'utiliser le fait que Haskell est purement fonctionnelle pour écrire un programme qui génère tous les types dont vous avez besoin et les insère dans le programme réel? Est-ce une telle technique exist? Par tous les moyens ne font si je suis tout simplement donnant ici quelque chose de base (je suis sans doute): -)

Modifier En ce moment, j'ai découvert fundeps . Je vais devoir réfléchir un peu sur la façon dont ils se rapportent à ma question (éclairant commentaires en ce qui concerne ce sont appréciés).

Était-ce utile?

La solution

Modèle Haskell le permet . wiki a quelques liens utiles; en particulier Boulat de tutoriels .

La syntaxe de déclaration de niveau supérieur est celui que vous voulez. En tapant:

mkFoo = [d| data Foo = Foo Int |]

vous générez une épissure modèle Haskell (comme une fonction de compilation) qui va créer une déclaration pour data Foo = Foo Int juste en insérant la ligne $(mkFoo).

Bien que ce petit exemple est pas trop utile, vous pouvez fournir un argument à mkFoo de contrôler combien de déclarations différentes que vous voulez. Maintenant, un $(mkFoo 100) produira pour vous 100 nouvelles déclarations de données. Vous pouvez également utiliser TH pour générer des instances de classe de type. Mon package adaptatif-tuple est un très petit projet qui utilise modèle Haskell pour faire quelque chose de similaire.

Une autre approche serait d'utiliser Derive , qui instances de classe de type derive automatiquement . Cela pourrait être plus simple si vous avez besoin des instances.

Autres conseils

En outre il y a des techniques simples de programmation au niveau du type dans Haskell. Un exemple canonique suit:

-- A family of types for the natural numbers
data Zero
data Succ n

-- A family of vectors parameterized over the naturals (using GADTs extension)
data Vector :: * -> * -> * where
    -- empty is a vector with length zero
    Empty :: Vector Zero a
    -- given a vector of length n and an a, produce a vector of length n+1
    Cons  :: a -> Vector n a -> Vector (Succ n) a

-- A type-level adder for natural numbers (using TypeFamilies extension)
type family Plus n m :: *
type instance Plus Zero n = n
type instance Plus (Succ m) n = Succ (Plus m n)

-- Typesafe concatenation of vectors:
concatV :: Vector n a -> Vector m a -> Vector (Plus n m) a
concatV Empty ys = ys
concatV (Cons x xs) ys = Cons x (concatV xs ys)

Prenez un moment pour prendre ce. Je pense qu'il est assez magique que cela fonctionne.

Cependant, la programmation au niveau du type dans Haskell est la fonctionnalité-inquiétante étrangeté vallée - juste assez pour attirer l'attention sur combien vous ne pouvez pas le faire. langues dépendamment typées comme Agda , Coq et épigramme prendre ce style à sa limite et pleine puissance.

Modèle Haskell est beaucoup plus comme le style habituel LISP-macro de génération de code. Vous écrivez du code pour écrire un code, vous dites « insérer ok que le code généré ici ». Contrairement à la technique ci-dessus, vous pouvez écrire tout code récursivement spécifié de cette façon, mais vous ne recevez pas le très général typage comme on le voit dans concatV ci-dessus.

Vous avez quelques options pour faire ce que vous voulez. Je pense que métaprogrammation est un espace très intéressant, et à certains égards encore très jeune. Bonne exploration. : -)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top