
The bit about multiple parameters is, of course, correct. There is a MultiParamTypeClasses extension though. Also note that for some classes you'd need RankNTypes, like 'Monad' class:
class Monad m where return :: a -> m a ...
is translated as
data Monad m = Monad {return :: forall a. a -> m a, ...}
As for recursive definitions, well, that's the same issue I pointed before. Say you have a class
class Foo a where bar :: a -> Bool baz :: a -> Bool
and you implement it as
instance Foo Integer where bar n = n > 0 baz n = not (bar n)
Well, with datatypes you have
data Foo a = Foo {bar :: a -> Bool, baz :: a -> Bool}
and of course this would never work:
fooInteger :: Foo Integer fooInteger = Foo {bar = \n -> n > 0, baz = \n -> not (bar n)}
However this one will:
fooInteger = Foo {bar = \n -> n > 0, baz = \n -> not (bar fooInteger n)}
and it's the exact translation of the 'class' solution. Отправлено с iPad
17 июня 2014 г., в 1:03, martin
написал(а): Am 06/16/2014 09:28 PM, schrieb Miguel Mitrofanov:
Now, you can just as easy implement all that without classes:
data AppendNumber a = AppendNumber {appendNumber :: a -> Integer -> a} appendNumberInteger :: AppendNumber Integer appendNumberInteger = AppendNumber {appendNumber = \n d -> n + d} appendNumberString :: AppendNumber String appendNumberString = AppendNumber {appendNumber = \s d -> s ++ show d} increment :: AppendNumber a -> a -> a increment an n = appendNumber an n 1 main = print $ increment appendNumberInteger 2048
I just stumbled across some other things:
When I use classes I can implement one function in terms of another function of the same class. When I use data/newtype I can't seem to do this. So I can replace a class by a data/newtype only when it wraps around a single function.
Also I can use as many parameters as I like in data/newtype, but not in classes (if I stick to standard haskell)
Is this correct?