
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

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
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.

So are you saying
data Shish2 a = Holder2 a | Onion (Shish a) | Lamb (Shish a) | Tomato
(Shish a)
but then I'm having trouble with
meal6 = (Onion (Tomato (Lamb (Holder2 (Fork)))))
Couldn't match expected type `Shish a1'
with actual type `Shish2 a0'
* In the first argument of `Tomato', namely
`(Lamb (Holder2 (Fork)))'
In the first argument of `Onion', namely
`(Tomato (Lamb (Holder2 (Fork))))'
In the expression: (Onion (Tomato (Lamb (Holder2 (Fork)))
On Fri, Mar 12, 2021 at 4:08 PM Tikhon Jelvis
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
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.

I think the problem is that you have a typo such that this Shish2 is
dependent on some other data type named Shish. If you change the type name
to Shish (or change its definition to use Shish2) it works fine.
data Shish a = Holder2 a | Onion (Shish a) | Lamb (Shish a) | Tomato (Shish
a) deriving Show
data Rod = Dagger | Fork | Sword deriving Show
meal6 = (Onion (Tomato (Lamb (Holder2 (Fork)))))
On Fri, Mar 12, 2021 at 2:23 PM Galaxy Being
So are you saying
data Shish2 a = Holder2 a | Onion (Shish a) | Lamb (Shish a) | Tomato (Shish a)
but then I'm having trouble with
meal6 = (Onion (Tomato (Lamb (Holder2 (Fork)))))
Couldn't match expected type `Shish a1' with actual type `Shish2 a0' * In the first argument of `Tomato', namely `(Lamb (Holder2 (Fork)))' In the first argument of `Onion', namely `(Tomato (Lamb (Holder2 (Fork))))' In the expression: (Onion (Tomato (Lamb (Holder2 (Fork)))
On Fri, Mar 12, 2021 at 4:08 PM Tikhon Jelvis
wrote: 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
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.
_______________________________________________ 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.

So embarrassing. Thanks. Anyway, this is what works data Shish2 a = Holder2 a | Onion2 (Shish2 a) | Lamb2 (Shish2 a) | Tomato2 (Shish2 a) whatHolder2 (Holder2 (sh)) = sh whatHolder2 (Onion2 (sk)) = whatHolder2 sk whatHolder2 (Tomato2 (sk)) = whatHolder2 sk whatHolder2 (Lamb2 (sk)) = whatHolder2 sk meal6 = (Onion2 (Tomato2 (Lamb2 (Holder2 (Fork)))))
whatHolder2 meal6 Fork
However, I'm still wondering how to have an abstracted (x:xs) - like
pattern to collapse all the ingredients, i.e.,
whatHolder2 (Holder2 (sh)) = sh
whatHolder2 (shish2-head (shish2-tail)) = whatHolder2 shish2-tail
On Fri, Mar 12, 2021 at 4:44 PM Bob Ippolito
I think the problem is that you have a typo such that this Shish2 is dependent on some other data type named Shish. If you change the type name to Shish (or change its definition to use Shish2) it works fine.
data Shish a = Holder2 a | Onion (Shish a) | Lamb (Shish a) | Tomato (Shish a) deriving Show data Rod = Dagger | Fork | Sword deriving Show
meal6 = (Onion (Tomato (Lamb (Holder2 (Fork)))))
On Fri, Mar 12, 2021 at 2:23 PM Galaxy Being
wrote: So are you saying
data Shish2 a = Holder2 a | Onion (Shish a) | Lamb (Shish a) | Tomato (Shish a)
but then I'm having trouble with
meal6 = (Onion (Tomato (Lamb (Holder2 (Fork)))))
Couldn't match expected type `Shish a1' with actual type `Shish2 a0' * In the first argument of `Tomato', namely `(Lamb (Holder2 (Fork)))' In the first argument of `Onion', namely `(Tomato (Lamb (Holder2 (Fork))))' In the expression: (Onion (Tomato (Lamb (Holder2 (Fork)))
On Fri, Mar 12, 2021 at 4:08 PM Tikhon Jelvis
wrote: 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
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.
_______________________________________________ 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.

You're now looking at the difference between: -- list of booleans but the end has an Int data T1 = End1 Int | Node1 Bool T1 whatInt1 (End1 i) = i whatInt1 (Node1 _ xs) = whatInt1 xs and -- list of booleans but the end has an Int again but different data T2 = End2 Int | FalseNode2 T2 | TrueNode2 T2 whatInt2 (End2 i) = i -- the following two cases are unmergeable -- but there is a mitigation if you find out about "record syntax" whatInt2 (FalseNode2 xs) = whatInt2 xs whatInt2 (TrueNode2 xs) = whatInt2 xs Record syntax can mitigate it: data T3 = End3 Int | FalseNode3 {tail3 :: T3} | TrueNode3 {tail3 :: T3} whatInt3 (End3 i) = i whatInt3 r = whatInt3 (tail3 r) But I say "mitgate", not "solve", because it doesn't generalize to data Q = QI Int | QF {qtail :: Q} | QT {qtail :: Q} | BF{qleft, qright :: Q} | BT{qleft, qright :: Q} On 2021-03-12 7:59 p.m., Galaxy Being wrote:
However, I'm still wondering how to have an abstracted (x:xs) - like pattern to collapse all the ingredients, i.e.,
whatHolder2 (Holder2 (sh)) = sh whatHolder2 (shish2-head (shish2-tail)) = whatHolder2 shish2-tail
participants (4)
-
Albert Y. C. Lai
-
Bob Ippolito
-
Galaxy Being
-
Tikhon Jelvis