Beginners Digest, Vol 152, Issue 5

2021-03-12 Thread beginners-request
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

2021-03-12 Thread beginners-request
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