Je veux faire un type mise en œuvre sûre du calcul Tensor dans Haskell en utilisant GADT de, de sorte que les règles sont les suivantes:Haskell GADTs - faire un type de Tensor typées pour la géométrie de Riemann
- tenseurs sont metrices n-dimentionelles avec indecies qui peut être «à l'étage» ou «en bas» par exemple: - est un Tenseur sans indecies (un scalaire), est un Tenseur avec un index 'en haut', est un tenseur avec un tas de 'en haut' et ' downside 'indecies
Vous pouvez ajouter un tenseur du même type, ce qui signifie qu'ils ont la même signature d'inde. l'indice 0e du premier tenseur est du même type (haut ou en bas) que l'indice 0e du second tenseur et ainsi de suite ...
Vous pouvez MULTIPLIER tenseurs et obtenir de plus gros tenseurs, avec les concaténer ees,:
Je veux que le type vérificateur de Haskell ne me permettrait pas d'écrire du code qui n » t suivez ces règles, il ne compilerait pas autrement.
Voici ma tentative à l'aide GADTs:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TypeOperators #-}
data Direction = T | X | Y | Z
data Index = Zero | Up Index | Down Index deriving (Eq, Show)
plus :: Index -> Index -> Index
plus Zero x = x
plus (Up x) y = Up (plus x y)
plus (Down x) y = Down (plus x y)
data Tensor a = (a ~ Zero) => Scalar Double |
forall b. (a ~ Up b) => Cov (Direction -> Tensor b) |
forall b. (a ~ Down b) => Con (Direction -> Tensor b)
add :: Tensor a -> Tensor a -> Tensor a
add (Scalar x) (Scalar y) = (Scalar (x + y))
add (Cov f) (Cov g) = (Cov (\d -> add (f d) (g d)))
add (Con f) (Con g) = (Con (\d -> add (f d) (g d)))
mul :: Tensor a -> Tensor b -> Tensor (plus a b)
mul (Scalar x) (Scalar y) = (Scalar (x*y))
mul (Scalar x) (Cov f) = (Cov (\d -> mul (Scalar x) (f d)))
mul (Scalar x) (Con f) = (Con (\d -> mul (Scalar x) (f d)))
mul (Cov f) y = (Cov (\d -> mul (f d) y))
mul (Con f) y = (Con (\d -> mul (f d) y))
Mais je suis en train:
Couldn't match type 'Down with `plus ('Down b1)'
Expected type: Tensor (plus a b)
Actual type: Tensor ('Down b)
Relevant bindings include
f :: Direction -> Tensor b1 (bound at main.hs:28:10)
mul :: Tensor a -> Tensor b -> Tensor (plus a b)
(bound at main.hs:24:1)
In the expression: (Con (\ d -> mul (f d) y))
In an equation for `mul':
mul (Con f) y = (Con (\ d -> mul (f d) y))
Quel est le problème?
Vous avez écrit 'plus' comme une fonction (niveau de valeur), mais vous essayez de l'utiliser dans un type. Haskell ne peut pas faire ça. (Il pense que le 'plus' dans le type de retour de' mul' est un paramètre de type.) Utilisez les familles de types. –
J'ai utilisé des opérateurs de type – user47376
Puis-je vous recommander de considérer également [une approche sans tenseurs de tenseurs] (http://hackage.haskell.org/package/linearmap-category-0.3.2.0/docs/Math-LinearMap-Category .html), sans ces indices stupides ... – leftaroundabout