[Haskell-beginners] Recursion with a self-defined type

Galaxy Being borgauf at gmail.com
Sat Mar 13 04:24:44 UTC 2021


So because Onion Shishkebab in the type definition is technically a data
constructor *function,  *the (shkb == Onion) in the code is comparing
function-to-function, i.e., won't work. Thanks. The light finally went on.

On Fri, Mar 12, 2021 at 6:28 PM Matthew Low <mlow at ualberta.ca> wrote:

> 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 <borgauf at gmail.com> 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 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
>>
>>
>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
>>
> _______________________________________________
> Beginners mailing list
> Beginners at 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/374bd7f6/attachment-0001.html>


More information about the Beginners mailing list