2011-03-17 9 views
12

He estado revisando Haskell monoids and their uses, lo que me ha dado una buena comprensión de los conceptos básicos de los monoides. Una de las cosas introducidas en la entrada del blog es el Cualquier monoide, y es de uso como la siguiente:Escribe un Monoid máximo usando Maybe en Haskell

foldMap (Any . (== 1)) tree 
foldMap (All . (> 1)) [1,2,3] 

En una línea similar, he estado tratando de construir un monoide máxima y han llegado con la siguiente :

newtype Maximum a = Maximum { getMaximum :: Maybe a } 
     deriving (Eq, Ord, Read, Show) 

instance Ord a => Monoid (Maximum a) where 
     mempty = Maximum Nothing 
     [email protected](Maximum (Just x)) `mappend` Maximum Nothing = m 
     Maximum Nothing `mappend` y = y 
     [email protected](Maximum (Just x)) `mappend` [email protected](Maximum (Just y)) 
      | x > y = m 
      | otherwise = n 

pude construir un monoide máximo para un tipo específico - por ejemplo Núm por ejemplo, con bastante facilidad, pero quiero que sea útil para nada (con el requisito obvio que la nada es una instancia de Ord).

En este punto mi código se compila, pero eso es todo. Si trato de ejecutarlo me sale esto:

> foldMap (Just) [1,2,3] 

<interactive>:1:20: 
    Ambiguous type variable `a' in the constraints: 
     `Num a' arising from the literal `3' at <interactive>:1:20 
     `Monoid a' arising from a use of `foldMap' at <interactive>:1:0-21 
    Probable fix: add a type signature that fixes these type variable(s) 

No estoy seguro de si esto se debe a que estoy llamando mal, o porque mi monoide es incorrecta, o ambos. Agradecería cualquier orientación sobre dónde me estoy equivocando (tanto en términos de errores lógicos como del uso no idiomático de Haskell, ya que soy muy nuevo en el lenguaje).

- EDITAR -

Paul Johnson, en un comentario más abajo, sugirió dejar Tal vez fuera. Mi primer intento se ve así:

newtype Minimum a = Minimum { getMinimum :: a } 
     deriving (Eq, Ord, Read, Show) 

instance Ord a => Monoid (Minimum a) where 
     mempty = ?? 
     [email protected](Minimum x) `mappend` [email protected](Minimum y) 
      | x < y  = m 
      | otherwise = n 

pero estoy claro cómo expresar mempty sin saber cuál debe ser el valor de un mempty. ¿Cómo podría generalizar esto?

+0

que ver cómo funciona, pero ¿por qué tener "Tal vez un" dentro del tipo máximo? Si acabas de decir "Maximum a", simplifica tu instancia. "Tal vez un" es una instancia de Ord, siempre que "a" lo sea, por lo que podría decir "Máximo (tal vez entero") y haría lo correcto. –

+0

@Paul Johnson Veo tu razonamiento detrás de dejar de lado el Tal vez, pero no sé cómo expresarlo. Agregué el código a mi pregunta anterior para que sea más legible. –

+2

Ahh, veo tu problema. Si agregaste "Limitado" como una restricción, entonces podrías hacer que mempty devuelva el límite inferior para Mínimo y Límite superior para Máximo. De lo contrario, estás en lo correcto; no hay una Cosa Correcta para que yo pueda hacer. Lo que significa que este no es un monoide. –

Respuesta

12

La función pasó a foldMap tiene que devolver un monoide, en este caso de tipo Maximum a:

> foldMap (Maximum . Just) [1,2,3] 
Maximum {getMaximum = Just 3} 
+0

Ahora que lo señalas, parece tan obvio :) ¡Gracias por tu respuesta! –

+1

ala 'Maximum foldMap Just [1,2,3] = Solo 3 - Dada la instancia adecuada de Newtype de Maximum. De este paquete: http://hackage.haskell.org/package/newtype –

Cuestiones relacionadas