Beginners Digest, Vol 152, Issue 5
Send Beginners mailing list submissions to beginners@haskell.org To subscribe or unsubscribe via the World Wide Web, visit http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners or, via email, send a message with subject or body 'help' to beginners-requ...@haskell.org You can reach the person managing the list at beginners-ow...@haskell.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Beginners digest..." Today's Topics: 1. Type * and * -> * (Galaxy Being) 2. Re: Type * and * -> * (Bob Ippolito) 3. Re: Type * and * -> * (Matthew Low) -- Message: 1 Date: Sat, 13 Mar 2021 00:18:26 -0600 From: Galaxy Being To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell Subject: [Haskell-beginners] Type * and * -> * Message-ID: Content-Type: text/plain; charset="utf-8" I found this interesting page <https://wiki.haskell.org/Peano_numbers> at Wiki Haskell. Confusing, however, is how it first establishes data Peano = Zero | Succ Peano It says Here Zero and Succ are values (constructors). Zero has type Peano, and Succ has type Peano -> Peano. but then it breaks down each member further a few lines later data Zero data Succ a and then says Zero has kind *, and Succ has kind * -> *. The natural numbers are represented by types (of kind *) Zero, Succ Zero, Succ (Succ Zero) etc. Why is it giving two separate treatments and what is meant by the * and * -> * ? There's something fundamental I'm missing. If anyone knows of a really thorough and definitive *and *understandable treatment of Haskell types, I'd appreciate it. LB -- next part -- An HTML attachment was scrubbed... URL: <http://mail.haskell.org/pipermail/beginners/attachments/20210313/f3d48623/attachment-0001.html> -- Message: 2 Date: Fri, 12 Mar 2021 22:52:13 -0800 From: Bob Ippolito To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell Subject: Re: [Haskell-beginners] Type * and * -> * Message-ID: Content-Type: text/plain; charset="utf-8" The first definition is only used as an analogy, it’s a way to represent Peano numbers as values. The second definition is only related to the first in that it uses the same concept. It is not a breakdown of the first one, it is a completely separate (and incompatible) way to represent Peano numbers at the type level (and only as types, notice there are no constructors). You can not define both of these in the same module with the same names. In Haskell a kind is (basically) the type of a type. In modern GHC to make it even more clear (and to free up * for type operators) you can say Type instead of *. Zero has the kind Type (or *) because it has no arguments, just like Zero has the type Peano because the constructor has no arguments. Succ has the kind Type -> Type because you pass it a Type as an argument to get a concrete Type. Maybe also has the kind Type -> Type, as does []. Generally, beginner Haskell doesn’t use any of this type level programming. If this is a topic of interest, I recommend this book: https://thinkingwithtypes.com On Fri, Mar 12, 2021 at 22:19 Galaxy Being wrote: > I found this interesting page <https://wiki.haskell.org/Peano_numbers> at > Wiki Haskell. Confusing, however, is how it first establishes > > data Peano = Zero | Succ Peano > > It says > > Here Zero and Succ are values (constructors). Zero has type Peano, > and Succ has type Peano -> Peano. > > but then it breaks down each member further a few lines later > > data Zero > data Succ a > > and then says > > Zero has kind *, and Succ has kind * -> *. The natural numbers are > represented by types (of kind *) Zero, Succ Zero, Succ (Succ Zero) etc. > > Why is it giving two separate treatments and what is meant by the * and * > -> * ? There's something fundamental I'm missing. > > If anyone knows of a really thorough and definitive *and *understandable > treatment of Haskell types, I'd appreciate it. > > LB > ___ > Beginners mailing list > Beginners@haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners > -- next part -- An HTML attachment was scrubbed... URL: <http://mail.haskell.org/pipermail/beginners/attachments/20210312/34683842/attachment-0001.html> -- Message: 3 Date: Fri, 12 Mar 2021 23:53:19 -0700 From: Matthew Low To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell Subject: Re: [Haskell-beginn
Beginners Digest, Vol 152, Issue 4
Send Beginners mailing list submissions to beginners@haskell.org To subscribe or unsubscribe via the World Wide Web, visit http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners or, via email, send a message with subject or body 'help' to beginners-requ...@haskell.org You can reach the person managing the list at beginners-ow...@haskell.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Beginners digest..." Today's Topics: 1. Recursion with a self-defined type (Galaxy Being) 2. Re: Recursion with a self-defined type (Matthew Low) 3. Re: Recursion with a self-defined type (Galaxy Being) -- Message: 1 Date: Fri, 12 Mar 2021 10:19:16 -0600 From: Galaxy Being To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell Subject: [Haskell-beginners] Recursion with a self-defined type Message-ID: Content-Type: text/plain; charset="utf-8" I'm trying to translate *The Little MLer *into Haskell. I've got this data Shishkebab = Skewer | Onion Shishkebab | Lamb Shishkebab | Tomato Shishkebab deriving Show Then I have this which works veggieKebab :: Shishkebab -> Bool veggieKebab Skewer = True veggieKebab (Onion (shk)) = veggieKebab shk veggieKebab (Tomato (shk)) = veggieKebab shk veggieKebab (Lamb (shk)) = False > veggieKebab (Tomato (Onion (Tomato (Onion Skewer True but I'm wondering if I could do something like this veggieKebab :: Shishkebab -> Bool veggieKebab Skewer = True veggieKebab (shkb (sk)) | (shkb == Onion) || (shkb == Tomato) = veggieKebab sk | otherwise = False This doesn't work, giving a "Parse error in pattern: shkb". I've been advised that I'm trying to treat what is a data constructor like a variable, but I can't fathom what that means in this case. What I'm trying to leverage is what I've learned from dealing with lists and recursion through the consed list. So if effect I'm trying to recurse through a consed Shishkebab object. It works in the first case, but hyow could I do this in this more generic way like the second try does? LB -- next part -- An HTML attachment was scrubbed... URL: <http://mail.haskell.org/pipermail/beginners/attachments/20210312/418bdcae/attachment-0001.html> -- Message: 2 Date: Fri, 12 Mar 2021 17:27:21 -0700 From: Matthew Low To: The Haskell-Beginners Mailing List - Discussion of primarily beginner-level topics related to Haskell Subject: Re: [Haskell-beginners] Recursion with a self-defined type Message-ID: Content-Type: text/plain; charset="utf-8" Pattern matches in Haskell are based on matching specific data constructors, with underscores `_` as a "match anything" mechanism. So one way to achieve something like what you want is veggieKebab :: Shishkebab -> Bool veggieKebab Skewer = True veggieKebab (Onion (shk)) = veggieKebab shk veggieKebab (Tomato (shk)) = veggieKebab shk veggieKebab _ = False This works because the matches are considered in top-to-bottom order, so the last case only matches if all the others fail to. I'm not sure if it helps to build insight or not, but if you look at the the types of your data constructors in GHCI, you get, for example: λ> :t Onion Onion :: Shishkebab -> Shishkebab So even if you could pattern match as you wanted (veggieKebab (shkb (sk)) | (shkb == Onion)), you'd still be stuck with the problem of trying to compare two functions for equality, which isn't easy (and not something Haskell lets you do for arbitrary functions). You could get close to what you originally wrote by using a few more helper functions: startsWithOnion :: Shishkebab -> Bool startsWithOnion (Onion _) = True startsWithOnion _ = False startsWithTomato :: Shishkebab -> Bool startsWithTomato (Tomato _) = True startsWithTomato _ = False restOfKebab :: Shishkebab -> Shishkebab restOfKebab Skewer = Skewer restOfKebab (Onion rst) = rst restOfKebab (Tomato rst) = rst restOfKebab (Lamb rst) = rst veggieKebab :: Shishkebab -> Bool veggieKebab Skewer = True veggieKebab kebab | startsWithOnion kebab || startsWithTomato kebab = veggieKebab (restOfKebab kebab) | otherwise = False On Fri, Mar 12, 2021 at 9:19 AM Galaxy Being wrote: > I'm trying to translate *The Little MLer *into Haskell. I've got this > > data Shishkebab = Skewer | Onion Shishkebab | Lamb Shishkebab | Tomato > Shishkebab deriving Show > > Then I have this which works > > veggieKebab :: Shishkebab -> Bool > veggieKebab Skewer = True > veggieKebab (Onion (shk)) = veggieKebab shk > veggieKebab (Tomato (shk)) = veggieKebab shk > veggieKebab (Lamb (shk)) = False > > > veggieKebab (Tomato (Onion (Tomato (Onion Skewe