[un seguimiento de la respuesta de Gabriel González]
La notación adecuada para las limitaciones y las cuantificaciones en Haskell es la siguiente:
<functions-definition> ::= <functions> :: <quantified-type-expression>
<quantified-type-expression> ::= forall <type-variables-with-kinds> . (<constraints>) => <type-expression>
<type-expression> ::= <type-expression> -> <quantified-type-expression>
| ...
...
clases pueden ser omitidos, así como forall
s Ranking-1 tipos:
<simply-quantified-type-expression> ::= (<constraints-that-uses-rank-1-type-variables>) => <type-expression>
por ejemplo:
{-# LANGUAGE Rank2Types #-}
msum :: forall m a. Monoid (m a) => [m a] -> m a
msum = mconcat
mfilter :: forall m a. (Monad m, Monoid (m a)) => (a -> Bool) -> m a -> m a
mfilter p ma = do { a <- ma; if p a then return a else mempty }
guard :: forall m. (Monad m, Monoid (m())) => Bool -> m()
guard True = return()
guard False = mempty
o sin Rank2Types
(ya que sólo tienen tipos de rango-1 aquí), y el uso de CPP
(J4F):
{-# LANGUAGE CPP #-}
#define MonadPlus(m, a) (Monad m, Monoid (m a))
msum :: MonadPlus(m, a) => [m a] -> m a
msum = mconcat
mfilter :: MonadPlus(m, a) => (a -> Bool) -> m a -> m a
mfilter p ma = do { a <- ma; if p a then return a else mempty }
guard :: MonadPlus(m,()) => Bool -> m()
guard True = return()
guard False = mempty
El "problema" es que no podemos escribir
class (Monad m, Monoid (m a)) => MonadPlus m where
...
o
class forall m a. (Monad m, Monoid (m a)) => MonadPlus m where
...
Es decir, forall m a. (Monad m, Monoid (m a))
se puede usar como una restricción independiente, pero no se puede crear un alias con una nueva clase de tipo paramétrica para los tipos *->*
.
Esto es porque el mecanismo de clase de tipos Defintion funciona así:
class (constraints[a, b, c, d, e, ...]) => ClassName (a b c) (d e) ...
es decir, los rhs lado introducen variables de tipo, no los LHS o forall
en los LHS.
En su lugar, tenemos que escribir clase de tipos 2-paramétricos:
{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-}
class (Monad m, Monoid (m a)) => MonadPlus m a where
mzero :: m a
mzero = mempty
mplus :: m a -> m a -> m a
mplus = mappend
instance MonadPlus [] a
instance Monoid a => MonadPlus Maybe a
msum :: MonadPlus m a => [m a] -> m a
msum = mconcat
mfilter :: MonadPlus m a => (a -> Bool) -> m a -> m a
mfilter p ma = do { a <- ma; if p a then return a else mzero }
guard :: MonadPlus m() => Bool -> m()
guard True = return()
guard False = mzero
Contras: tenemos que especificar segundo parámetro cada vez que utilizamos MonadPlus
.
Pregunta: ¿cómo
instance Monoid a => MonadPlus Maybe a
se puede escribir si MonadPlus
es uno paramétrico clase de tipos?MonadPlus Maybe
de base
:
instance MonadPlus Maybe where
mzero = Nothing
Nothing `mplus` ys = ys
xs `mplus` _ys = xs
no funciona como Monoid Maybe
:
instance Monoid a => Monoid (Maybe a) where
mempty = Nothing
Nothing `mappend` m = m
m `mappend` Nothing = m
Just m1 `mappend` Just m2 = Just (m1 `mappend` m2) -- < here
:
(Just [1,2] `mplus` Just [3,4]) `mplus` Just [5,6] => Just [1,2]
(Just [1,2] `mappend` Just [3,4]) `mappend` Just [5,6] => Just [1,2,3,4,5,6]
Análogamente, forall m a b n c d e. (Foo (m a b), Bar (n c d) e)
da lugar a (7 - 2 * 2) clase de tipos -PARAMETRIC si queremos *
tipos, (7 - 2 * 1) -param clase de tipo etric para tipos * -> *
y (7 - 2 * 0) para tipos * -> * -> *
.
Si bien estoy seguro de que hay una pregunta interesante aquí, en su forma actual es esencialmente "¿Qué problemas han tenido que enfrentar edwardk y tekmo?" , que solo puede ser realmente respondido por esas personas. Como tal, no creo que esta pregunta sea adecuada para SO en su forma actual. – hammar
Me parece que "¿qué problemas hay con los que alguien se haya encontrado?" es más la intención aquí. Cualquiera que tenga problemas similares podría, espero, reconocerlo y presentar la pregunta tan bien como las personas específicas cuyas quejas se mencionan. –
Sí, @ C.A.McCann captó mi intento bastante bien, aunque no estoy particularmente buscando "¿qué problemas te has encontrado?" tanto como "¿cuál es el problema subyacente?" Espero que una buena respuesta explique en qué es * el sistema actual de restricciones *, cuáles son sus debilidades y si existen planes para mejorarlo. –