John Bugner
2017-07-06 05:04:17 UTC
In imperative OO languages, there are for/while loops:
A for-loop often looks like this:
for (i = 0; i < 100; i++) {
a[i] = f(i);
}
In Elm (and Haskell), we have the neat `map` function that captures this
pattern:
map f a
A while-loop looks like this:
while (!isDone(s)) {
f(s);
}
Haskell has the `until` function that captures this pattern:
until isDone f s
Elm lacks this function. Is there a reason why? What's the current elmic
way of doing this? Explicit recursion, I assume?
Anyways, it seems that somebody else already yearned for `until` like me,
and made this module:
http://package.elm-lang.org/packages/Chadtech/elm-loop/1.0.2/Loop ...
I note though, that he changed the order of the arguments from Haskell's
`(a -> Bool) -> (a -> a) -> a -> a` to `(a -> Bool) -> a -> (a -> a) -> a`.
I'm not sure why. If he wanted to match the usual impOO order, then why not
`a -> (a -> Bool) -> (a -> a) -> a` instead ? Anyways, I think Haskell's
order is the right order, because it let's you make useful closures, like
this:
collatz : Int -> Int
collatz =
let
u : Int -> Int
u n =
if isEven n
then n // 2
else 3 * n + 1
in
until ((==) 1) u
This function is elegantly defined, but not very useful, because the result
of every (positive) number will simply return 1 (mathematicians strongly
suspect so, anyways). What's interesting is the *sequence* that a number
makes on it's way down to 1. So I made a function that repeats like
`until`, but also records each intermediate result in a list, like `scanl`:
scanUntil : (a -> Bool) -> (a -> a) -> a -> List a
scanUntil p u s =
let
p_ : List a -> Bool
p_ xs = case xs of
[] -> True
x :: _ -> p x
u_ : List a -> List a
u_ xs = case xs of
[] -> []
x :: _ -> u x :: xs
in
until p_ u_ [s]
I'm not sure that `scanUntil` is the best name. Can anybody think of a
better name? I also note that list that it returns is reversed compared to
`scanl`'s and Haskell's `iterate` function (
https://hackage.haskell.org/package/base-4.7.0.2/docs/Prelude.html#v:iterate
), but feels right because the most useful value is probably going to be
the last one calculated. But maybe this doesn't matter, because if you
really want the last one calculated, then you'd just use `until` instead
anyways.
Anyways... answers, thoughts, and comments are welcome.
A for-loop often looks like this:
for (i = 0; i < 100; i++) {
a[i] = f(i);
}
In Elm (and Haskell), we have the neat `map` function that captures this
pattern:
map f a
A while-loop looks like this:
while (!isDone(s)) {
f(s);
}
Haskell has the `until` function that captures this pattern:
until isDone f s
Elm lacks this function. Is there a reason why? What's the current elmic
way of doing this? Explicit recursion, I assume?
Anyways, it seems that somebody else already yearned for `until` like me,
and made this module:
http://package.elm-lang.org/packages/Chadtech/elm-loop/1.0.2/Loop ...
I note though, that he changed the order of the arguments from Haskell's
`(a -> Bool) -> (a -> a) -> a -> a` to `(a -> Bool) -> a -> (a -> a) -> a`.
I'm not sure why. If he wanted to match the usual impOO order, then why not
`a -> (a -> Bool) -> (a -> a) -> a` instead ? Anyways, I think Haskell's
order is the right order, because it let's you make useful closures, like
this:
collatz : Int -> Int
collatz =
let
u : Int -> Int
u n =
if isEven n
then n // 2
else 3 * n + 1
in
until ((==) 1) u
This function is elegantly defined, but not very useful, because the result
of every (positive) number will simply return 1 (mathematicians strongly
suspect so, anyways). What's interesting is the *sequence* that a number
makes on it's way down to 1. So I made a function that repeats like
`until`, but also records each intermediate result in a list, like `scanl`:
scanUntil : (a -> Bool) -> (a -> a) -> a -> List a
scanUntil p u s =
let
p_ : List a -> Bool
p_ xs = case xs of
[] -> True
x :: _ -> p x
u_ : List a -> List a
u_ xs = case xs of
[] -> []
x :: _ -> u x :: xs
in
until p_ u_ [s]
I'm not sure that `scanUntil` is the best name. Can anybody think of a
better name? I also note that list that it returns is reversed compared to
`scanl`'s and Haskell's `iterate` function (
https://hackage.haskell.org/package/base-4.7.0.2/docs/Prelude.html#v:iterate
), but feels right because the most useful value is probably going to be
the last one calculated. But maybe this doesn't matter, because if you
really want the last one calculated, then you'd just use `until` instead
anyways.
Anyways... answers, thoughts, and comments are welcome.
--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.