Hello! Following a discussion with a Haskell/math-minded colleague, I’ve realized there are multiple List Applicative instances (
succeed pattern). Notably, zipping and “all combinations”.
List.mapN functions from
elm/core are zipping, and I’ve created a package with
mapN functions that instead give you all combinations (the Cartesian product).
Here it is: elm-list-cartesian 1.0.2
Motivating example, illustrating the difference:
List.map2 (+) [ 1, 2 ] [ 100, 200, 300 ] --> [ 101, 202 ] List.Cartesian.map2 (+) [ 1, 2 ] [ 100, 200, 300 ] --> [ 101, 201, 301, 102, 202, 302 ]
I feel like it has the potential to free you from hard-to-read and hard-to-write nested
List.concatMap expressions or converting to/from a list of lists with
colors = [Red, Green, Blue] numbers = [1, 2, 3, 4] players = [Human, NPC] allCombinationsBefore : List (Color, Int, Player) allCombinationsBefore = colors |> List.concatMap (\color -> numbers |> List.concatMap (\number -> players |> List.map (\player -> (color, number, player)) ) ) allCombinationsAfter : List (Color, Int, Player) allCombinationsAfter = List.Cartesian.map3 (\color number player -> (color, number, player)) colors numbers players
So, that’s it! Hopefully a nicer API for some not-so-common tasks (I’m glad the zipping List behaviour is the default, the need for it comes up much more often in FE work than “get all combinations” in my experience).
Aside: Of course,
List.Extraalready had most of these functions already in the form of
lift2etc., but it was missing the Cartesian version of
andMap– you’d have to define it yourself with
cartesianAndMap = List.Extra.lift2 (|>)).
[ identity ] -- using List.singleton as our `pure` |> List.Extra.andMap [1,2,3] -- or `List.Zip.andMap` from my pkg -->  ❌
We’d need a
succeedfunction that returns an infinite list (or somehow get around the zipping behaviour in a different way).
I’ve remarked about this briefly in the documentation for