Talk:Haskell/Type declarations

tuples and types
Up to this point, the reader has encountered tuples and some basic motivation for types. Seems like we need to make the connection between tuples and what we're doing here, something along the lines of "well, you already know how to make your own types; just combine things with lists and tuples; but it's still not very convenient... sometimes you want to name a type; and sometimes you have two things that look like they're the same, but for some reason or another, you want to enforce that they are of different types." We could start off with type synonyms, actually, just make synonyms for tuples... and eventually discover that it's not quite good enough. Then data... and then flip back and point out that synonyms can also be used on data. -- Kowey 03:15, 30 December 2006 (UTC)


 * This was the first section that I don't feel very comfortable with. Your comment helped actually. I didn't start to realize the possible usefulness of creating your own Types until I was well into the section. I am also a little confused by constructor functions. I see now how they can be used but I feel like I'm missing the bigger picture or the logic behind some of the syntax.--Jberryman (talk) 02:15, 4 March 2008 (UTC)


 * In the spirit of these commentaries I wrote a brief introduction. Ideally it should be a natural follow-up to the introduction of Haskell/Type basics - I even considered referring directly to the phone book example, but it would get too verbose. Also, it is maybe a little too abstract... The ideal approach would likely be a didactic step-by-step example as Kowey suggested above, but given my lack of Haskell experience I didn't feel compelled to try pulling that off.


 * By the way, I believe it would be good to swap this sub-chapter with the Simple IO one. Not only because this topic is a natural continuation of Type basics, but also because having this comparatively short section at the end of the chapter and placed after the long and conceptually tricky introduction to actions makes it easy for readers to miss the point due to lack of context. --Duplode (talk) 05:50, 29 April 2010 (UTC)


 * Concerning the oder of chapters, I'm not sure whether it's a good idea to put the Simple IO after the type declarations. How about the following:
 * At the moment, the wikibook is still kinda messy. In particular, the structure behind the division of the beginner's track into four separate parts is not clear (except for the monads, those are clear). Ideally, however, I envision the following structure:
 * Part 1 - "Minimal Haskell", enables the reader to write Haskell programs, in the sense that he can encode any functionality he dreams of in Haskell, albeit restricted to a subset of the syntax.
 * Part 2 - "Elementary Haskell", enables the reader to read most Haskell programs and write better ones.
 * Part 3 - "Haskell with Class", enables the reader to write Haskell libraries, using modules, type classes and so on.
 * Part 4 - Monads


 * From this, it follows that the type declarations should go into part 2 and only type synonyms should be mentioned in part 1. Simple IO has to stay in part 1, though, because it's clearly required for doing IO stuff.
 * -- apfe&lambda;mus 14:01, 3 May 2010 (UTC)

CFG looking types
I was just wondering why this doesn't work: data BalancedParen = OpenParen CloseParen | OpenParen BalancedParen CloseParen | BalancedParen BalancedParen it gives: $ ghci ___        ___ _  / _ \ /\  /\/ __(_) / /_\// /_/ / /  | |      GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| |      http://www.haskell.org/ghc/ \____/\/ /_/\____/|_|     Type :? for help.

Loading package base-1.0 ... linking ... done. Prelude&gt; :l varfun.hs Compiling Main            ( varfun.hs, interpreted )

varfun.hs:1:46: Multiple declarations of `Main.OpenParen' Declared at: varfun.hs:1:22 varfun.hs:1:46 Failed, modules loaded: none. Prelude&gt;

I also tried this text in varfun.hs: data Palindrome = A Palindrome A | B Palindrome B | A | B | A A | B B It gave: $ ghci ___        ___ _  / _ \ /\  /\/ __(_) / /_\// /_/ / /  | |      GHC Interactive, version 6.4.2, for Haskell 98. / /_\\/ __ / /___| |      http://www.haskell.org/ghc/ \____/\/ /_/\____/|_|     Type :? for help.

Loading package base-1.0 ... linking ... done. Prelude&gt; :l varfun.hs Compiling Main            ( varfun.hs, interpreted )

varfun.hs:1:60: Multiple declarations of `Main.A'   Declared at: varfun.hs:1:52 varfun.hs:1:60

varfun.hs:1:60: Multiple declarations of `Main.A'   Declared at: varfun.hs:1:18 varfun.hs:1:60

varfun.hs:1:66: Multiple declarations of `Main.B'   Declared at: varfun.hs:1:56 varfun.hs:1:66

varfun.hs:1:66: Multiple declarations of `Main.B'   Declared at: varfun.hs:1:35 varfun.hs:1:66 Failed, modules loaded: none. Prelude&gt;

Answer
Well, one thing is as the compiler complains: you can't have multiple declarations of the same type using the same constructor, so this is bad: data MyWonderfulType = Bar Int | Bar Char -- bad: too many Bars Whereas this is ok data MyWonderfulType = Foo Int | Bar Char

Note incidentally that this too is bad... data MyNiceType = Foo data MyOtherType = Foo -- too many Foos

The basic intuition for this is that when you say  in some piece of code, not the type declaration itself, but simply trying to use , you want the Haskell compiler to know what you're talking about. In the case above, we have an ambiguity... was that a  you wanted or a  ?

The other issue is simply a question of syntax, in that a type declaration looks like this... data MyType = Constructor TypeArg1 TypeArg2 ... TypeArgN where TypeArg1..TypeArgN are themselves types. (Incidentally, it's ok if the constructor and the type have the same name)

The implications being that a type like the below...

data Palindrome = A Palindrome A

You've got a constructor, followed by arguments   and. That's all well and good, except that
 * 1) It's probably not what you had in mind
 * 2) ... The type   isn't defined anywhere else in your code

Here's something which would probably work better

data A = A data B = B data Palindrome = P1 A Palindrome A | P2 B Palindrome B | P3 A A

Note how I give a constructor (P1...P3) for each alternative in the CFG, and that each constructor is different (can't have multiple declarations, remember? Now, you might be tempted to do something like this... -- not going to work data Alphabet = A | B | C data Palindrome = P1 A Palindrome A | P2 B Palindrome B | P3 A A

Because what comes after the constructor has to be a type, whereas,  in this case, is NOT a type (  is a type, as is  ). You could try something like this: data Alphabet = A | B | C data Palindrome = P1 Alphabet Palindrome Alphabet | P3 Alphabet Alphabet

But then we'd no longer be dealing with a CFG, would we?

Hope this helps. For more questions, please try the haskell mailing list (or perhaps haskell-cafe), or the #haskell IRC channel on irc.freenode.net -- Kowey 06:57, 15 August 2006 (UTC)

Error
johnSmith = Birthday { name = "John Smith", date = Date 7 3 1986}'

name and date are not in scope here (unless i missed something) -- should they read anniName and anniDate? 82.70.93.66 13:32, 2 September 2006 (UTC)


 * Fixed, thanks. -- Kowey 20:33, 2 September 2006 (UTC)

newtype
data X = Y Char newtype X' = Y' Char

X' has 257 possible values while X has 258.

showAnniversary
showAnniversary didn't work the way the text is implying it should have (I think). I got the impression it should somehow magically tie in with show, so you could just type. But instead you have to type showAnniversary smithWedding. I find this chapter a tad confusing.... 24.65.49.167 (talk) 04:36, 20 March 2008 (UTC) (aka user:Bawolff)


 * Well, you absolutely could. Just add a deriving (Show) clause to the data declaration, and it'll work like you expect.
 * But the problem is, that requires two advanced ideas: typeclasses, and instance derivation. And I'm pretty sure those topics don't get covered for a while yet. Having the reader work through things the hard way serves the useful purpose of demonstrating the drudgery we can automate and abstract away later. --Gwern (contribs)
 * As a C/C++ programmer trying to learn elementary Haskell, I have to agree with the original poster. Just because it's too early to teach classes and derivation in general doesn't mean you can't use them in this case to aid this tutorial. K&R doesn't have a problem with showing how to print literal text with printf even though the concepts of how to really take advantage of or write your own printf-style function don't come until much later. At the very least, mentioning this issue and giving a pointer toward the later subject that provides the solution would be useful. 24.4.188.251 (talk) 06:50, 9 April 2008 (UTC)
 * It's not exactly relevant to answer messages from two years ago, but I felt like commenting anyway. I would rather strongly disagree with the "C/C++ programmer" above in that I can't see how mentioning deriving (Show) at this very early stage could aid the tutorial. One of the key roles of this module is introducing constructor functions in an easy to understand way for an absolute newbie - and, as far as that purpose is concerned, the less distracting syntactic sugar and advanced functionality the better. In fact, I would even consider moving the discussion about type synonyms to some other place... --Duplode (talk) 06:35, 2 May 2010 (UTC)

Additional exercise...
I think the following exercise would be good to be added:

Define the following

I could add it by myself, but I am not really sure about the proper answers. My guess would be:


 * 1) The values True and False are already bound to the data structure  . Therefore a second bind of the same (True resp. False) lets the compiler question which True it should take, either from the Prelude or the newly defined.
 * 2) no real clue
 * 3) I think it could look like   or   . But to be honest, I have no clue, what the difference between the two definition is.


 * A year and a half later... (sorry, this page was missing from my watchlist.)


 * 1. Yup, that's it.


 * 2 and 3. You have a few options:
 * (define a wholly new data type using different names for the constructors from the ones in the Prelude) and then ;
 * (define a type synonym, which is exactly equivalent to  except in name) and then  ; and
 * (define a new data type which is merely a wrapper for ) and then  . Incidentally, that is a case in which you normally would use   in real code. That might look like
 * I suspect you originally had the first option in mind for your test.


 * Duplode (discuss • contribs) 15:00, 13 July 2015 (UTC)