2011-07-13 21 views
5

que estoy tratando de crear una "jerarquía" de las clases de tipos algebraicos, de la siguiente manera:jerarquía de clases tipo semigrupo/Monoid/Grupo de errores Haskell

class Semigroup a where 
    (.*) :: a -> a -> a 
    foldr1 (.*) = foldl1 (.*) -- GHCi error: "`foldr1' is not a (visible) method of class `Semigroup'" 

class (Semigroup a) => Monoid a where 
    identity :: a 
    (.*) identity = id :: a -> a -- GHCi error: "`.*' is not a (visible) method of class `Monoid'" 

class (Monoid a) => Group a where 
    inverse :: a -> a 

Por lo tanto, los grupos son monoides y monoides son semigrupos. Sin embargo, recibo errores de que las clases no pueden ver las funciones de su clase principal.

Estos errores me molestan porque supuse que al escribir (por ejemplo) class (Semigroup a) => Monoid a la clase Monoid a podría ver la función (.*). Y, además, el tipo de foldr1 en el Preludio no tiene restricciones, por lo que asumí que foldr1 funcionaría en este contexto.

+0

Para aclarar, lo que estaba buscando era implementar los axiomas para semigrupos, monoides y grupos como clases de tipos. Por lo tanto, la clase 'Semigroup a' debe venir con una operación binaria asociativa' (. *) :: a -> a -> a'. Traté de implicar la asociatividad usando 'foldr1', pero este fue mi tercer intento, precedido por' (x. * Y). * Z = x. * (Y. * Z) 'y' \ xyz -> (x. * y). * z = \ xyz -> x. * (y. * z) '. Luego quería que la clase 'Monoid a' fuera una subclase de' Subgroup a', heredando la operación binaria '(. *)' Y mostrando cómo interactúa con el elemento 'identity' (es decir, trivialmente). –

+1

¿Está tratando de establecer las leyes para '(. *)'? No puedes hacer eso en las declaraciones de clase; Creo que debes mirar las reglas de reescritura para obtener el efecto que deseas. – yatima2975

+1

@ yatima2975 Lo busqué y aún no lo he probado, pero parece exactamente lo que estoy buscando. Muchas gracias –

Respuesta

5

Haskell no permite que usted declare (o ejecutar) ecuaciones en términos (como parece que quiere hacer). Esto es por una razón muy práctica: probar la igualdad entre términos arbitrarios en un lenguaje de programación tan rico como Haskell es indecidible. Verificación de una prueba construida por humanos a menudo es decidible, pero también es algo molesto tener que escribir y rastrear estas pruebas durante la programación.

Aún así, si este es el tipo de cosas que desea hacer de forma regular, hay son idiomas que hacen esto posible; el término a buscar es "tipos dependientes". Por ejemplo, Coq y Agda son quizás los dos lenguajes dependientes más populares en este momento, y cada uno de ellos haría que escribir un tipo habitado solo por semigrupos buenos (respetuosos de la ley) (o monoidios) sea muy simple.

4

No estoy seguro de lo que estás tratando de hacer.

Si usted está tratando de proporcionar un valor predeterminado para foldr1 en Semigroup, y un valor por defecto para (.*) en Monoid, entonces no se puede.

  • foldr1 se define en el preludio como una función no-clase de tipos, por lo que no se puede dar una definición local en Semigroup
  • (.*) es parte de la clase Semigroup. Usted puede dar a sus valores en Semigroup casos, y se puede dar un valor por defecto para que en la clase Semigroup, pero no se puede dar a su valor en la clase Monoid (o Monoid casos)

Si eres tratando de proporcionar un valor predeterminado para (.*) en Semigroup, y un valor predeterminado para identity en Monoid, entonces está utilizando la sintaxis incorrecta.

En lugar intentar algo así como

class Semigroup a where 
    (.*) :: a -> a -> a 
    (.*) = {-something-} 

o

class Semigroup a where 
    (.*) :: a -> a -> a 
    x .* y = {-something-} 
Cuestiones relacionadas