2017-09-07 5 views
1

J'essaie d'utiliser la sous-classe, dans Haskell, pour appliquer une spécificité incrémentale à mes classes et ne pas avoir de chance.Comment appliquer une spécificité incrémentale, en utilisant une sous-classe dans Haskell?

Ma première tentative:

module Subclassing where 

class SuperClass a where 
    type TheType a :: * 
    theFunc :: TheType a -> TheType a 

class SuperClass b => SubClass b where 
    type TheType b = Int 

data MyType 

instance SubClass MyType where 
    theFunc x = x + x 

a abouti à ceci:

Subclassing.hs:10:8: error: 
    ‘TheType’ is not a (visible) associated type of class ‘SubClass’ 

Subclassing.hs:15:3: error: 
    ‘theFunc’ is not a (visible) method of class ‘SubClass’ 

Je me demandais s'il y avait une méthode pour exposer les syntactique types/méthodes de la superclasse à la sous-classe. Donc, j'ai cherché un peu sur le net, mais je n'ai rien trouvé.

Dans ma deuxième tentative, j'ai essayé de forcer la question, en définissant une instance universelle des superclasse, contraintes sur la sous-classe:

{-# LANGUAGE TypeFamilies   #-} 
{-# LANGUAGE AllowAmbiguousTypes #-} 
{-# LANGUAGE FlexibleInstances  #-} 
{-# LANGUAGE UndecidableInstances #-} 

module Subclassing where 

class SuperClass a where 
    type TheType a :: * 
    theFunc :: TheType a -> TheType a 

class SubClass b 
instance SubClass c => SuperClass c where 
    type TheType c = Int 

data MyType 

instance SubClass MyType 
instance SuperClass MyType where 
    theFunc x = x + x 

testFunc :: SuperClass d => [TheType d] -> TheType d 
testFunc = sum . (map theFunc) 

Il a donné ceci:

Subclassing2.hs:25:23: error: 
    • Overlapping instances for SuperClass a0 
     arising from a use of ‘theFunc’ 
     Matching givens (or their superclasses): 
     SuperClass d 
      bound by the type signature for: 
        testFunc :: SuperClass d => [TheType d] -> TheType d 
      at Subclassing2.hs:24:1-52 
     Matching instances: 
     instance SubClass c => SuperClass c 
      -- Defined at Subclassing2.hs:15:10 
     instance SuperClass MyType -- Defined at Subclassing2.hs:21:10 
     (The choice depends on the instantiation of ‘a0’) 
    • In the first argument of ‘map’, namely ‘theFunc’ 
     In the second argument of ‘(.)’, namely ‘(map theFunc)’ 
     In the expression: sum . (map theFunc) 

Dans mon troisième tentative, j'ai essayé de faire de la sous-classe un type plutôt qu'une classe. (j'ai réalisé que cela aurait une portée limitée, en raison de la limitation du champ unique du constructeur newtype valeur, mais était d'idées.):

{-# LANGUAGE TypeFamilies   #-} 
{-# LANGUAGE AllowAmbiguousTypes #-} 

module Subclassing where 

class SuperClass a where 
    type TheType a :: * 
    theFunc :: TheType a -> TheType a 

newtype SubClass = SubClass { unSubClass :: Int -> Int } 
instance SuperClass SubClass where 
    type TheType SubClass = Int 
    theFunc = unSubClass 

testFunc :: SuperClass d => [TheType d] -> TheType d 
testFunc = sum . (map theFunc) 

Et il a donné ceci:

Subclassing3.hs:17:13: error: 
    • Couldn't match type ‘Int -> Int’ with ‘Int’ 
     Expected type: TheType SubClass -> TheType SubClass 
     Actual type: SubClass -> Int -> Int 
    • In the expression: unSubClass 
     In an equation for ‘theFunc’: theFunc = unSubClass 
     In the instance declaration for ‘SuperClass SubClass’ 

Subclassing3.hs:20:23: error: 
    • Couldn't match type ‘TheType a0’ with ‘TheType d’ 
     Expected type: TheType a0 -> TheType d 
     Actual type: TheType a0 -> TheType a0 
     NB: ‘TheType’ is a type function, and may not be injective 
     The type variable ‘a0’ is ambiguous 
    • In the first argument of ‘map’, namely ‘theFunc’ 
     In the second argument of ‘(.)’, namely ‘(map theFunc)’ 
     In the expression: sum . (map theFunc) 
    • Relevant bindings include 
     testFunc :: [TheType d] -> TheType d 
      (bound at Subclassing3.hs:20:1) 
+2

Je pense que vous n'avez pas encore vraiment compris ce qu'est une classe. Une classe de type Haskell est très différente d'une classe dans les langages OO typiques. Définir une instance d'une classe (ce qui peut être fait pour des types concrets, comme le newtype dans votre troisième tentative) est fondamentalement différent de la définition d'une sous-classe. – leftaroundabout

+3

Pour répondre à cette question probablement [XY] (https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), il serait utile d'en savoir un peu plus sur ce que vous veux tout ça pour. En particulier, la famille de types 'TheType' ne semble pas avoir de sens; pourquoi pensez-vous que vous avez besoin d'une famille de type associée là-bas? – leftaroundabout

+1

Ce n'est certainement pas quelque chose que Haskell est conçu pour supporter. Cela dit, j'ai fait un [proof of concept gist] (https://gist.github.com/harpocrates/38ec83098cd45d7e8bccbb2d7001acb5#file-subtype-hs) à ce sujet il y a quelque temps. Si c'est ce que vous cherchez, la question est probablement une copie de https://stackoverflow.com/q/41504364/3072788. – Alec

Répondre

0

Votre première supposition me semble assez sensible, mais non, Haskell ne laisse pas définir les types ou méthodes associés dans une définition de (sous-) classe.