[Haskell-cafe] data/newtype vs. class

Miguel Mitrofanov miguelimo38 at yandex.ru
Mon Jun 16 19:28:54 UTC 2014


Well, classes are datatypes. The only difference is that the compiler is able to derive the value of the class for you.

Small example. Let's say we have a class

> class AppendNumber a where
>   appendNumer :: a -> Integer -> a

some instances

> instance AppendNumber Integer where
>   appendNumber n d = n + d
> instance AppendNumber String where
>   appendNumber s d = s ++ show d

and some functions with it

> increment :: AppendNumber a => a -> a
> increment n = appendNumber n 1

that you can use with specific types

> main = print $ increment 2048

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

The only two differences are that you have to 1) give names to the instances, and 2) manually insert the correct values in two last lines ('an' and 'appendNumberInteger' respectively). Classes simplify things, telling the compiler "I only care about one value of that type, and here it is; insert it whenever suitable".

Now, I haven't seen your code, but it seems that you attempted to use something like

> class Named a where
>   getName :: a -> String

and then you were shown the better option, which is to just use String. Well, by the rules above, it translates to

> data Named a = Named {getName :: a -> String}

and in all your functions the value of type 'a' would be paired with, essentially, the function "a -> String". If that's the situation you find yourself in, it's only natural to unite both in one value like this:

> data WithName = forall a. WithName a (a -> String)

and use one value instead of two. But that calls for more refactoring; namely, the "WithName" data type above is isomorphic to "String", since you can't do anything else with it rather than apply it's second component to the first one. That's the reasoning behind removing classes in a nutshell.

16.06.2014, 22:58, "martin" <martin.drautzburg at web.de>:
> Hello all,
>
> I find myself trying to define a class, where a newtype would suffice.
>
> E.g. once I was pondering over "named" things and my initial thought was "well that's a class, which asks for a function
> 'getName'". But then here http://www.haskell.org/pipermail/haskell-cafe/2010-June/078803.html someone showed me a
> solution without any classes.
>
> Recently I was pondering over "timed things" (things which change at specific ponts in time) and again my initial
> thought was "that's a class, which asks for a method 'at'".
>
> Then I remembered things like State, i.e. data types which wrap around functions. State is not a class, which asks for a
> function 'nextState', it is all defined with data.
>
> Can someone give me some guidance, when to use classes and when to use data? Are the two concepts interchangeable in
> some scenarios?
>
> Martin
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list