Elm Copenhagen, February 2018 Meetup @MobileLife

With some input from Basile Henry, also attended the Meetup, I have made a few modifications to the code in order to support m :: * -> * ( (a -> b) -> m a -> m b ) as good as Elm allows us to do it, but without transitioning to a signature hell as seen in elm-data , see References for more information on that library.

Obviously not really monads

As a fellow Coding Pirates volunteer, Hans Bugge Grathwohl , pointed out:

1 2 3 4 5 6 7 8 9 10 11 odd : { fmap : ( Int -> String ) -> Float -> List Char , join : List Char -> String } odd = { fmap = \ f x -> String . toList ( f ( truncate x )) , join = String . fromList } weird : String weird = 4.5 |> bind odd toString

this can’t really be considered monads as there is no relation between a and ma as well as mb and mmb .

Code Snippet

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 module Main exposing ( .. ) import Html exposing ( br , div , text ) bind : { monad | fmap : ( a -> mb ) -> ma -> mmb , join : mmb -> mb } -> (( a -> mb ) -> ma -> mb ) bind { fmap , join } f m = join ( fmap f m ) maybe : { fmap : ( a -> b ) -> Maybe a -> Maybe b , join : Maybe ( Maybe c ) -> Maybe c } maybe = { fmap = Maybe . map , join = \ mm -> case mm of Nothing -> Nothing Just m -> m } list : { fmap : ( a -> b ) -> List a -> List b , join : List ( List c ) -> List c } list = { fmap = List . map , join = List . concat } result : { fmap : ( a -> b ) -> Result c a -> Result c b , join : Result e ( Result e d ) -> Result e d } result = { fmap = Result . map , join = \ mm -> case mm of Result . Err e -> Result . Err e Result . Ok m -> m } foo : Maybe Int foo = Just 42 |> bind maybe ( \ x -> Just ( x + 1 )) |> bind maybe ( \ x -> Just ( x + 1 )) |> bind maybe ( \ x -> Just ( x + 1 )) bar : List String bar = [ 0 , 1 , 2 , 4 , 5 ] |> bind list ( \ x -> [ x + 10 , x + 20 ]) |> bind list ( \ x -> [ x + 100 ]) |> bind list ( \ x -> [ toString x ]) baz : Result String Int baz = Result . Ok " 42 " |> bind result String . toInt |> bind result ( \ x -> Result . Ok ( x + 1 )) |> bind result ( \ x -> Result . Ok ( x + 1 )) |> bind result ( \ x -> Result . Ok ( x + 1 )) qux : Result String Int qux = Result . Ok " 42 " |> bind result ( String . trim >> Result . Ok ) |> bind result String . toInt |> bind result ( \ x -> Result . Ok ( x + 1 )) |> bind result ( \ x -> Result . Ok ( x + 1 )) |> bind result ( \ x -> Result . Ok ( x + 1 )) main = div [] [ text <| "-- Maybe: " ++ toString foo , br [] [] , text <| "-- Lists: " ++ toString bar , br [] [] , text <| "-- Result: " ++ toString baz , br [] [] , text <| "-- Result: " ++ toString qux ]

Code output:

-- Maybe: Just 45 -- Lists: ["110","120","111","121","112","122","114","124","115","125"] -- Result: Err "could not convert string ' 42 ' to an Int" -- Result: Ok 45

References: