sintaxis functions fromintegral data haskell typeclass

functions - syntax record haskell



Taquigrafía de tipografía Haskell (4)

Por lo tanto, tengo un par de clases de tipos que usaré mucho, y quiero evitar especificar ambas cada vez. Básicamente, en lugar de poner

:: (Ord a, Fractional a, Ord b, Fractional b, ... Ord z, Fractional z) =>

al comienzo de todas mis especificaciones de tipo, preferiría poner

:: (OrdFractional a, OrdFractional b, ... OrdFractional z)

Entonces, mi idea inicial sobre cómo hacer esto fue simplemente declarar una nueva clase de tipos

module Example where class (Fractional a, Ord a) => OrdFractional a example :: (OrdFractional a, OrdFractional b) => (a,b) -> (a,b) -> (a,b) -> Bool example (x1,y1) (x2,y2) (x3,y3) = (x1/x2 < x2/x3) && (y1/y2 < y2/y3)

Pero esto no funcionó tan automágicamente como hubiera deseado:

% ghci Prelude> :l Example.hs Ok, modules loaded: Example. Prelude Example> example (1::Float,3::Float) (2,2) (3,1) <interactive>:1:0: No instance for (OrdFractional Float) arising from a use of `example'' at <interactive>:1:0-39 Possible fix: add an instance declaration for (OrdFractional Float) In the expression: example (1 :: Float, 3 :: Float) (2, 2) (3, 1) In the definition of `it'': it = example (1 :: Float, 3 :: Float) (2, 2) (3, 1)

La creación manual de instancias parece un arrastre, así que, a continuación, pensé que podría intentar crear instancias automáticamente:

module Example where class OrdFractional a instance (Fractional a, Ord a) => OrdFractional a example :: (OrdFractional a, OrdFractional b) => (a,b) -> (a,b) -> (a,b) -> Bool example (x1,y1) (x2,y2) (x3,y3) = (x1/x2 < x2/x3) && (y1/y2 < y2/y3)

Pero al compilador no le gustó eso:

ghc -c Example.hs Example.hs:4:0: Illegal instance declaration for `OrdFractional a'' (All instance types must be of the form (T a1 ... an) where a1 ... an are type *variables*, and each type variable appears at most once in the instance head. Use -XFlexibleInstances if you want to disable this.) In the instance declaration for `OrdFractional a''

Entonces, ¿hay alguna manera de que pueda hacer esto?



Cuando el compilador diga " Use -XFlexibleInstances ", deberías intentar agregar

{-# LANGUAGE FlexibleInstances #-}

a la parte superior de su fuente (¡y vaya a leer la documentación para saber qué hace, por supuesto!).

En este caso específico, esto hará que su código funcione:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}

Se requieren instancias flexibles para habilitar el contexto => en el encabezado de instancia, y se requieren instancias indecidibles porque el compilador, al manejar un contexto OrdFractional a , puede terminar agregando Fractional a y Ord a al contexto, lo que no ayuda directamente a determinar finalmente a , y bajo circunstancias adecuadamente horribles, la verificación de tipo puede divergir; al compilador realmente no le gusta eso. (Probablemente no te guste si el compilador continúa para siempre o se queda sin memoria, tampoco).


No.

Su solución de una superclase que implica las otras clases es lo más cercano a lo que usted quiere que es posible en Haskell. Aunque eso requiere instancias manuales de esa nueva clase, a veces se usa, por ejemplo, en la biblioteca de reescritura .

Como CesarB mencionó que los alias de clase hacen lo que quieres (y más), pero son solo una propuesta que ha existido durante años y nunca se ha implementado, probablemente porque hay numerosos problemas con ella. En cambio, varias otras propuestas han surgido, pero ninguna de ellas se implementó tampoco. (Para obtener una lista de esas propuestas, consulte esta página de Haskellwiki ). Uno de los proyectos en Hac5 fue modificar el GHC para incluir un pequeño subconjunto de alias de clase llamados sinónimos de contexto (que hacen exactamente lo que está pidiendo aquí y nada más) , pero lamentablemente nunca fue terminado.


Con la extensión ConstraintKinds introducida en GHC 7.4, las restricciones ahora son tipos de Constraint tipo, por lo que puede usar sinónimos de tipo ordinario para obtener lo que desea:

{-# LANGUAGE ConstraintKinds #-} type OrdFractional a = (Ord a, Fractional a)