[Haskell-cafe] SML vs Haskell types

Tikhon Jelvis tikhon at jelv.is
Fri Mar 12 22:08:28 UTC 2021


Onion of 'a shish is equivalent to Onion (Shish a) in Haskell rather than
Onion a (Shish a).

The latter version in Haskell creates a constructor with two arguments,
something like Onion of ('a * 'a shish) would in SML. (Or, at least,
OCaml—not 100% familiar with SML syntax myself!)

On Fri, Mar 12, 2021, 14:03 Galaxy Being <borgauf at gmail.com> wrote:

> Hello,
>
> This is my first post here, and it's an odd one, I'll admit. Basically,
> I'm trying to translate the material in *The Little MLer *to Haskell, the
> TLMLer being an excellent types workout. So in SML I have this
>
> datatype 'a shish = Bottom of 'a | Onion of 'a shish | Lamb of 'a shish |
> Tomato of 'a shish
>
> and this
>
> datatype rod =  Dagger | Fork | Sword
>
> and then this SML function
>
> fun is_veggie (Bottom (x)) = true
>   | is_veggie (Onion (x)) = is_veggie (x)
>   | is_veggie (Lamb (x)) = false
>   | is_veggie (Tomato (x)) = is_veggie (x)
>
> which has no problem handling tis
>
> is_veggie (Onion(Tomato(Bottom(Dagger))))
>
> Now, in Haskell I've translated this (with minor alterations) to
>
> data Shish a = Holder a | Onion a (Shish a) | Lamb a (Shish a) | Tomato a
> (Shish a)
> data Rod = Dagger | Fork | Sword
>
> However, in Haskell these two expressions are different things entirely
>
> meal4 = Tomato Dagger (Onion Fork (Lamb Spear (Holder Fork)))
> meal5 = (Tomato (Onion (Lamb (Holder Fork))))
>
> Here's my attempt at handling meal4 with a Haskell isVeggie
>
> isVeggie (Holder (sh)) = True
> isVeggie (Onion sh (sk)) = isVeggie sk
> isVeggie (Tomato sh (sk)) = isVeggie sk
> isVeggie (Lamb sh (sk)) = False
>
> This works for meal4, but not for meal5. And yet in the SML world their
> is_veggie handles (Onion(Tomato(Bottom(Dagger)))) just fine. TLMLer says
>
> Onion (Tomato (Bottom (Dagger)))
>
> belongs to the type rod shish, while in Haskell
>
> Onion (Tomato (Holder (Dagger)))
>
> is a bizarre nested beast due to the fact that the data constructor
> variable of Onion is Tomato (Holder (Dagger)) etc. etc.
>
> Can a single Haskell version of isVeggie handle both meal4 and meal5? No?
> I thought so. But then how would a separate Haskell version of isVeggie
> handle meal5 -- or is it just too weird? Also, but not critical, how
> could the Haskell isVeggie be done with guards, i.e., just like a consed
> list is matched on (x:xs) in the recursion case? I can see that 1:2:3:[]
> and Onion (Tomato (Bottom (Dagger))) are both conses, but the latter I
> don't know how to break out into head and tail for a guard case where the
> individual food items were not mentioned explicitly. IOW, this doesn't work
>
> isVeggieKebab :: Shish -> Bool
> isVeggieKebab Holder (sk) = True
> isVeggieKebab (shkb (sk)) | (shkb == Onion) || (shkb == Tomato) =
> isVeggieKebab sk
>                         | otherwise = False
>
> I'm feeling some doom and gloom about this project. Right at the start
> this seems to be an insurmountable difference between SML and Haskell type
> systems. Or I simply don't understand something fundamental here.
>
> LB
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20210312/77c47c2d/attachment.html>


More information about the Haskell-Cafe mailing list