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


Peter:technologist:  10 hours ago

(edited)

:point_up:1

Peter:technologist:  10 hours ago

I assume you are not looking for an answer, since it’s an exercise of self learning. But do you need/want any hints?

anthony.kit  10 hours ago

@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)

hayleigh  10 hours ago

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

:point_up:1

janiczek:radioactive_sign:  10 hours ago

@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?

:raised_hands:1

anthony.kit  10 hours ago

@hayleigh oh, you are right, I got confused myself:sweat:, can you provide some hits for the challenge, a more dynamic way.. (edited)

Peter:technologist:  10 hours ago

@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:1

janiczek:radioactive_sign:  10 hours ago

g g g g g "al" I can see how to do, but I have my doubts about the second one :slightly_smiling_face:

hayleigh  10 hours ago

It wants a function that can be called

g () () () () “al”

@janiczek

anthony.kit  10 hours ago

In Haskell, I will be able to use class to solve this problem, but in Elm, how? (edited)

janiczek:radioactive_sign:  10 hours ago

yes but it should be possible to call it with

g () () () () "al"

g () () () "al"

g () () "al"

hayleigh  10 hours ago

Of course

:shrug:1

hayleigh  10 hours ago

Let me walk home and I’ll do it ^.^

:raised_hands:1

Peter:technologist:  10 hours ago

@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

hayleigh  10 hours ago

OK well I’ll caveat with its only possible if you get creative with the interpretation of the question/examples a bit :joy:

anthony.kit  10 hours ago

since Elm treat () as a type :sweat_smile:, but what about g[][][][]['al'] (edited)

hayleigh  10 hours ago

You still have the general problem of “return a function unless its “al” and then return a string” to work around

hayleigh  10 hours ago

Alright, im home. time to get creative :smile:

hayleigh  9 hours ago

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

hayleigh  9 hours ago

:smiling_imp:

:smiling_imp:1

sebbes  9 hours ago

Can we add as many o as we want in your solution @hayleigh?

hayleigh  9 hours ago

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

hayleigh  9 hours ago

implementation is left as an exercise to the reader :sunglasses:

hayleigh  9 hours ago

Here's the same trick being used for a variadic add:

Html.text <| add one one one one one String.fromInt

Peter:technologist:  9 hours ago

implementation is left as an exercise to the reader :sunglasses:

Ah, yes, the good 'ol "the margins on my notebook is too small to prove this theorem" trick :joy:

Peter:technologist:  9 hours ago

since Elm treat () as a type :sweat_smile:, but what about g[][][][]['al']

That also won't work because:

hayleigh  8 hours ago

here is the general explanation http://mlton.org/Fold

hayleigh  8 hours ago

and

g f = f “g”

o s f = f (a ++ “o”)

al s = s ++ “al”

janiczek:radioactive_sign:  8 hours ago

:exploding_head:

janiczek:radioactive_sign:  8 hours ago

I didn't believe you could pull it off, wasn't familiar with this trick at all :sweat_smile:

Now to figure out how it works

janiczek:radioactive_sign:  8 hours ago

Feels kinda like continuations

janiczek:radioactive_sign:  8 hours ago

I'm getting all tripped up on whether it evaluates like (g o) al or g (o al) :smile:

janiczek:radioactive_sign:  7 hours ago

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)

hayleigh  7 hours ago

g o has the type (String -> a) -> a (the same as g)

hayleigh  7 hours ago

(as does (g o) o and ((g o) o) o and so on...)

janiczek:radioactive_sign:  7 hours ago

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

janiczek:radioactive_sign:  7 hours ago

what a mind twister

hayleigh  7 hours ago

very clever eh

janiczek:radioactive_sign:  7 hours ago

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.

janiczek:radioactive_sign:  7 hours ago

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

hayleigh  7 hours ago

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)

janiczek:radioactive_sign:  7 hours ago

BTW seems like there is no talk about the pattern (I googled for fp fold printf :shrug:) - speaker senses tingling! :smile:

hayleigh  7 hours ago

Stealing my twitter engagement :angry: :joy:

:smile:1

janiczek:radioactive_sign:  6 hours ago

This is my headcanon for the types currently :smile:

hayleigh  6 hours ago

yeah that's pretty much exactly how i imagined it too