Skip to content

Instantly share code, notes, and snippets.

@diegonc
Last active December 18, 2016 04:22
Show Gist options
  • Save diegonc/79199c5c97315d54efa3a63fa6b6ad0d to your computer and use it in GitHub Desktop.
Save diegonc/79199c5c97315d54efa3a63fa6b6ad0d to your computer and use it in GitHub Desktop.
[Elm] Have some fun reducing a list while unwrapping a Result

Say there's an l of type List a, an e of type b which represent an empty collection and a function add of type a -> b -> Result x b.

add inserts an a into a b which is an operation that could fail.

I'd like to apply a fold through l using add as the reducer so that in the end I have a Result with either the b that contains all of the as in the list or an error.

However, I can't just do List.foldl add e l because of the signature of add. So, what I did is to introduce a new function that unwraps the accumulator to apply it to add in case it's an Ok and pass thru if it is an Err. The code is below:

reducer : (a -> b -> Result x b) -> a -> Result x b -> Result x b
reducer fn a b =
  case b of
    Ok c -> fn a c
    Err _ -> b

Then I can do List.foldl (reducer add) (Ok e) l (yay)

It looks like a pretty general function and I started to suspect there must be a more idiomatic way of doing this. Anyone has an idea? Some useful function in the Result module I should be aware of?

@ Elm Slack

take a look at andThen from the Result module, see if you can reimplement your reducer function with it

Oh, I can do

reducer fn a b = Result.andThen (fn a) b 

right? That would allow me to remove one argument from reducer 🙂

@ Elm Slack

yep! or you can just put it into the fold as is List.foldl (\a b -> Result.andThen (add a) b) (Ok e) l

yeah, that's not too bad. thanks! I was hoping some composition wizardry would allow me to reduce it even more 😁

@ Elm Slack

lol trying to golf it down further too I get too much enjoyment out of this

Hell, yes! But currently, I'm out of ideas 😬 Any further suggestions are appreciated!

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