Hans van Thiel wrote:
> On Mon, 2008-08-25 at 00:33 +0200, Ben Franksen wrote:
>> Hans van Thiel wrote:
>> > so 'The Greenhorn's Guide to becoming a Monad Cowboy' is on
>> > http://www.muitovar.com/monad/moncow.xhtml>>>> "(Recall that a type definition is just like a data definition, but with
>> no choice operator (|).)" First, you mean to say 'newtype', not 'type'
>> (as in the code).
> Thanks for the feedback. If and when I get some more comments and error
> reports, I'll try to fix them.
>> Second, a newtype may also contain only one data element (i.e.
>> one type expression after the constructor), not many, as in a data type
>> definition.
> Yes, that's what I thought too, but then I got confused by State s a,
> which looks to have two. Could you explain?
Most probably you are confusing type and data constructor. This is a common
error and a hurdle I remember falling over more than once. It is due to the
fact that in Haskell both are in completely separate name spaces,
nevertheless both use capitalized names. Thus people often use the same
name for both, especially with newtype, as there may only be one data
constructor. In your case you have
newtype State s a = State { runState :: (s -> (a, s)) }
where the type constructor takes two (type-) arguments (even for a newtype
it can take as many as you like), but the data constructor takes only one
value as argument, namely a function from s to (a,s).
Clear now?
>> Third, newtype is unlifted.
> The books I use for reference, the Craft and SOE, don't seem to mention
> this. I have to confess, I don't really understand the difference
> between newtype and data. Again, an explanation would be appreciated.
Did Ryan's explanation help?
> As a general comment on the teaching of Haskell, all books and
> tutorials, which I've seen, appear to treat this aspect of Haskell as if
> it were self explanatory. This while the better known imperative
> languages don't have anything like it. Only Real World Haskell explains
> algebraic data types to some satisfaction (IMHO, of course).
This is one of the more difficult aspects Haskell, IME. I found the Haskell
wiki book (http://en.wikibooks.org/wiki/Haskell) very useful, especially
the chapter on denotational semantics
(http://en.wikibooks.org/wiki/Haskell/Denotational_semantics).
If you have a background in imperative languages, especially low-level ones
like C, then it may help to think of the values of a lifted type (data ...)
as being represented by a pointer to the data proper (e.g. a struct),
whereas values of an unlifted type (newtype ...) are represented exactly as
the argument type. A value of a lifted type always has one additional value
in its type, namely bottom. You may think of bottom as being represented by
a null pointer. In fact, one could say that, in Java, Objects are always
lifted whereas basic types like integer are unlifted.
Now, before I get shot down by the purists, I know that this is not exactly
true, since bottom is also the value of an infinite loop, so Java in fact
has a 'real' bottom in addition to null, etc. See the above cited online
book chapter for a more precise (and still very readable) treatment.
Cheers
Ben