2010-11-17 18 views
5

Estoy tratando de representar los bordes pesados. Eventualmente quiero que OutE sea una instancia de Eq y Ord, con la restricción de que etype es una instancia de Eq y Ord. Suponga que he archivo siguiente como temp.hs:Agregar restricciones de tipo al contexto de las declaraciones de instancia en Haskell

data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype} 

applyFunBy accessor ordfun = (\x y -> (ordfun (accessor x) (accessor y))) 

instance Eq (OutE vtype etype) where 
    --(==) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool 
    --(/=) :: Ord etype => (OutE vtype etype) -> (OutE vtype etype) -> Bool 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

cuando me carga esta en ghci, consigo los siguientes errores:

temp.hs:10:19: 
    Could not deduce (Ord etype) 
     from the context (Eq (OutE vtype etype)) 
     arising from a use of `edgeValue' at temp.hs:10:19-27 
    Possible fix: 
     add (Ord etype) to the context of the instance declaration 
    In the first argument of `applyFunBy', namely `edgeValue' 
    In the expression: applyFunBy edgeValue (==) 
    In the definition of `==': == = applyFunBy edgeValue (==) 

temp.hs:11:19: 
    Could not deduce (Ord etype) 
     from the context (Eq (OutE vtype etype)) 
     arising from a use of `edgeValue' at temp.hs:11:19-27 
    Possible fix: 
     add (Ord etype) to the context of the instance declaration 
    In the first argument of `applyFunBy', namely `edgeValue' 
    In the expression: applyFunBy edgeValue (/=) 
    In the definition of `/=': /= = applyFunBy edgeValue (/=) 
Failed, modules loaded: none. 

Si incluirá las líneas para las firmas de tipos de (==) y (\ =), me sale:

temp.hs:6:1: 
    Misplaced type signature: 
    == :: 
     (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool 

temp.hs:7:1: 
    Misplaced type signature: 
    /= :: 
     (Ord etype) => (OutE vtype etype) -> (OutE vtype etype) -> Bool 

Respuesta

5

Usted limitada etype seas Ord en el Defintion de OutE:

data (Ord etype) => OutE vtype etype = ... 

Pero en el Eq ejemplo, en realidad estás tratando de definir la instancia de cualquier etype sin restricciones.

instance Eq (OutE vtype etype) where 

Por supuesto, esto no funciona ya OutE sí se acaba de definir para Ord etype s, por lo que tendrá que añadir la restricción de clase de tipos a la definición ejemplo también.

instance (Ord etype) => Eq (OutE vtype etype) where 

Tenga en cuenta que una definición de cualquiera == o /= es suficiente para la clase de tipos que funcione.


Tenga en cuenta que a menudo es más fácil y por lo tanto considerado mejor estilo de no tener limitaciones en la clase de tipos data -Tipos, pero sólo en casos/métodos que realmente requieren la funcionalidad de la clase de tipos.

En muchos casos, uno no necesita la restricción y simplemente termina con firmas de tipo innecesariamente torpes.

Tome p. Ej. algún tipo de mapa ordenado Ord key => Map key value.

¿Qué pasa si solo queremos enumerar todas las claves? ¿O obtienes la cantidad de elementos? No necesitamos las claves para ser Ord para estos, ¿por qué no acaba de dejar el mapa sin restricciones con sencillo

getKeys :: Map key value -> [key] 
getLength :: Map key value -> Int 

y sólo tiene que añadir la clase de tipos cuando realmente lo necesitamos en una función como

insert :: Ord key => key -> value -> Map key value 
2
data (Ord etype)=> OutE vtype etype = OutE {destVertex:: vtype, edgeValue::etype} 

Primera edición: Esto se consdered mal estilo. Sus declaraciones de tipos de datos no deberían tener restricciones. Deje las restricciones a las funciones, al igual que el paquete de contenedores.

instance Eq (OutE vtype etype) where 

Segundo "problema". Solo puede agregar deriving (Eq) después de su declaración de datos. Supongo que sabe que está escribiendo y la instancia explícita de su propio aprendizaje (bueno para usted) ...

instance Eq (OutE vtype etype) where 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

Tercera cuestión: no se puede comparar los valores de la equidad si son de la clase Eq . Por lo que quiere decir etype se ve limitada por la ecuación:

instance (Eq etype) => Eq (OutE vtype etype) where 
    (==) = applyFunBy edgeValue (==) 
    (/=) = applyFunBy edgeValue (/=) 

En cuarto lugar, que en realidad no necesita escribir una instancia para ambos (==) y (/ =). Los valores predeterminados funcionarán una vez que defina uno de estos.

+0

'deriving (Eq)' generará operadores de igualdad basados ​​en ** todos ** campos de registro (y así generará una incómoda instancia de 'Eq' con' Eq vtype') mientras que la instancia explícita dada en la pregunta solo se compara en función de 'edgeValue '. – Dario

+0

Derecho, no me di cuenta de que estaba haciendo eso hasta después de escribir ese bit. Gracias por señalar eso. –

Cuestiones relacionadas