Skip to content

Instantly share code, notes, and snippets.

@mcmillhj
Created August 24, 2017 02:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mcmillhj/a1950b069f3c8e932470b50bb1074154 to your computer and use it in GitHub Desktop.
Save mcmillhj/a1950b069f3c8e932470b50bb1074154 to your computer and use it in GitHub Desktop.
example.sml
(* foldl type
fn: ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
*)
fun fromBase base = let
fun f (x, NONE ) = NONE
| f (x, SOME n) =
if x >= 0 andalso x < base then SOME(n * base + x)
else NONE
in
foldl f (SOME 0)
end
@mcmillhj
Copy link
Author

Conversation from #sml that helped get to this solution:


[20:56] <mcmillhj> I am having some trouble getting foldl to work with option types, I am sure I am overlooking something obvious. Would someone mind taking a look? https://gist.github.com/anonymous/3ee8bb4f872169d516fb7d7966e0518d
[20:56] <mcmillhj> thanks
[21:00] == groovy2shoes [~groovy2sh@unaffiliated/groovebot] has joined #sml
[21:12] == xcmw [~textual@2605:a000:132b:20d8:b994:4884:3e3c:5651] has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
[21:20] == lambda-11235 [~lambda-11@70.41.58.147] has joined #sml
[21:20] == xcmw [~textual@2605:a000:132b:20d8:b994:4884:3e3c:5651] has joined #sml
[21:45] == xcmw [~textual@2605:a000:132b:20d8:b994:4884:3e3c:5651] has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
[21:45] == xcmw [~textual@2605:a000:132b:20d8:b994:4884:3e3c:5651] has joined #sml
[22:11] <ski> mcmillhj : first match on `acc' to determine whether it's `NONE' or `SOME n' for some `n' of type `int'
[22:12] ski [~ski@remote11.chalmers.se] requested CTCP PING from mcmillhj: 1503540730 103116
[22:17] == xcmw [~textual@2605:a000:132b:20d8:b994:4884:3e3c:5651] has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
[22:23] <mcmillhj> ski: thanks, that was exactly what I needed https://gist.github.com/anonymous/88048de39b4a749a491d18471b451b92
[22:23] <mcmillhj> I was hoping it would look a little cleaner though, I was trying to model it after this Haskell solution https://github.com/exercism/haskell/blob/master/exercises/all-your-base/examples/success-standard/src/Base.hs
[22:23] <ski> you can define `f' like :
[22:25] <ski>   fun f (x,NONE  ) = NONE
[22:25] <ski>     | f (x,SOME n) = if x >= 0 andalso x < base
[22:25] <ski>                 then SOME (n * base + x)
[22:25] <ski>                 else NONE
[22:27] <mcmillhj> oh wow, that looks much cleaner. Thank you ski
[22:27] <ski> oh, that paste uses `foldM', not `foldl'
[22:28] <ski> you could define a `foldM' (for `option') if you wanted to. then your `f' would look more similar to that Haskell one
[22:29] <ski> (an alternative would be to use an exception instead of `NONE')
[22:30] <ski> oh .. and if you want to, you can also avoid giving `f' a name :
[22:30] <ski>   fun fromBase base = foldl
[22:30] <ski>         (fn f (x,NONE  ) => NONE
[22:31] <ski>           | f (x,SOME n) => ...)
[22:31] <ski>         (SOME 0)
[22:31] <ski> er, sorry, there shouldn't be `f's after `fn' and `|' there, scrap those
[22:32] <mcmillhj> ski: sorry to ask so many questions, but how does foldM differ from foldl?
[22:32] <mcmillhj> does it do some sort of implicit unwrapping of option types?
[22:32] <ski>   val foldl : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
[22:32] <ski>   val foldM : ('a * 'b -> 'b option) -> 'b -> 'a list -> 'b option  (* in this case *)
[22:33] <ski> (i suppose you could call it `fold_option' or something)
[22:34] <ski> then the function passed to `foldM' / `fold_option' would not need to check whether it's argument is `NONE' or `SOME n' (since `foldM' / `fold_option' itself would handle that)
[22:35] <mcmillhj> ah I see
[22:35] <mcmillhj> thanks so much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment