2021, July 8th https://elmlang.slack.com/archives/C0CJ3SBBM/p1625656998009600
anthony.kit Yesterday at 20:23
Hi everyone. Is it possible to solve this https://github.com/carbonfive/functional-programming-weekly-challenge/tree/master/Week002 by using Elm? The only possible solution I can think of is Recursive Type Aliases, but I am not too familiar with this, any ideas?
45 replies
(edited)
1
I assume you are not looking for an answer, since it’s an exercise of self learning. But do you need/want any hints?
@Peter I am looking for an answer, also happy with hints. Before asking this question, i have done a little bit of research, it seems Elm support Recursive Type Aliases: https://github.com/elm/compiler/blob/9d97114702bf6846cab622a2203f60c2d4ebedf2/hints/recursive-alias.md (edited)
Elm doesn't support recursive type aliases (and that link tells you so, too!)
The compiler cannot deal with values like this. It would just keep expanding forever.
Recursive types!
In cases where you want a recursive type, you need to actually create a brand new type. This is what the type keyword is for. ...
1
@Peter I would be interested in seeing how this can be done in Elm.
The goal is not to do g g g g g g g g g "al" but (((g ()) ()) ()) "al", right?
1
@hayleigh oh, you are right, I got confused myself, can you provide some hits for the challenge, a more dynamic way.. (edited)
@janiczek Either version works, pretty sure (but yeah, the syntactic translation is a bit ambiguous from JS -> Elm here). Let me whip up an Ellie.
1
g g g g g "al" I can see how to do, but I have my doubts about the second one
It wants a function that can be called
g () () () () “al”
In Haskell, I will be able to use class to solve this problem, but in Elm, how? (edited)
yes but it should be possible to call it with
g () () () () "al"
g () () () "al"
g () () "al"
Of course
1
Let me walk home and I’ll do it ^.^
1
@janiczek I think you're right, I was overzealous with my claim that it's possible. () doesn't work because you can't assign that as a type (okay, that should have been obvious in hindsight). I'd love to see how hayleigh does it, if it's possible! My naive attempt at a solution was:
type Recursive = () | String
goal : Int -> Recursive -> String
goal count rec =
case rec of
() ->
if count == 0 then
"go" ++ goal (count + 1)
else
"o" ++ goal (count + 1)
str ->
str
g = goal 0
g () () () "al" -- This does NOT work
OK well I’ll caveat with its only possible if you get creative with the interpretation of the question/examples a bit
since Elm treat () as a type , but what about g[][][][]['al'] (edited)
You still have the general problem of “return a function unless its “al” and then return a string” to work around
Alright, im home. time to get creative
main =
Html.div []
[ Html.p [] [ Html.text a ]
, Html.p [] [ Html.text b ]
, Html.p [] [ Html.text c ]
]
a = g o al
b = g o o al
c = g o o o al
1
Can we add as many o as we want in your solution @hayleigh?
main = Html.div []
[ Html.p [] [ Html.text a ]
, Html.p [] [ Html.text b ]
, Html.p [] [ Html.text c ]
, Html.p [] [ Html.text d ]
]
a = g o al
b = g o o al
c = g o o o al
d = g o o o o o o o o o o o o o al
yup
implementation is left as an exercise to the reader
Here's the same trick being used for a variadic add:
Html.text <| add one one one one one String.fromInt
implementation is left as an exercise to the reader
Ah, yes, the good 'ol "the margins on my notebook is too small to prove this theorem" trick
since Elm treat () as a type , but what about g[][][][]['al']
That also won't work because:
here is the general explanation http://mlton.org/Fold
and
g f = f “g”
o s f = f (a ++ “o”)
al s = s ++ “al”
I didn't believe you could pull it off, wasn't familiar with this trick at all
Now to figure out how it works
Feels kinda like continuations
I'm getting all tripped up on whether it evaluates like (g o) al or g (o al)
Am I roughly correct here?
g : (String -> a) -> a
g f = f "g"
-- `a` in the type will be `(String -> whatever)` because of the `o`
o : String -> (String -> a) -> a
o s f = f (s ++ "o")
-- `a` in the type can be `String` or `(String -> String)` depending on what you put after the `o`?
al : String -> String
al s = s ++ "al"
(edited)
g o has the type (String -> a) -> a (the same as g)
(as does (g o) o and ((g o) o) o and so on...)
g o al
(\f1 -> f1 "g") (\s1 f2 -> f2 (s1 ++ "o")) (\s2 -> s2 ++ "al") -- expanded to definitions
((\f1 -> f1 "g") (\s1 f2 -> f2 (s1 ++ "o")) (\s2 -> s2 ++ "al")) -- added parens, it goes (g o) al, not g (o al)
((\s1 f2 -> f2 (s1 ++ "o") "g") (\s2 -> s2 ++ "al") -- applied middle fn to the first fn
(\f2 -> f2 ("g" ++ "o")) (\s2 -> s2 ++ "al") -- applied "g" to the first fn
(\f2 -> f2 "go") (\s2 -> s2 ++ "al") -- evaluated ++
(\s2 -> s2 ++ "al") "go" -- applied second fn to the first fn
"go" ++ "al" -- applied "go" to the first fn
"goal" -- evaluated ++
what a mind twister
very clever eh
I would have never found that in my life.
Cool to see the usages:
This page describes a technique that enables convenient syntax for a number of language features that are not explicitly supported by Standard ML, including: variable number of arguments, optional arguments and labeled arguments, array and vector literals, functional record update, and (seemingly) dependently typed functions like printf and scanf.
Off-hand it may appear impossible that all of the above expressions are type correct SML — how can a function f accept a variable number of curried arguments? What could the type of f be?
Exactly, ML dude, EXACTLY
I'll admit i did ask some friends if there was some clever combinator trick to do this, but in my defence I was going in the right direction (although I don't think i'd have worked it out on my own without a heap of trial and error)
BTW seems like there is no talk about the pattern (I googled for fp fold printf ) - speaker senses tingling!
Stealing my twitter engagement
1
This is my headcanon for the types currently
yeah that's pretty much exactly how i imagined it too