GithubHelp home page GithubHelp logo

elm-applicatives-and-json-decoders's Introduction

Elm Applicatives & Json Decoders

FP Concepts They Don't Want You to Know About (Which Is Why All the Fun Stuff is Hidden in *.Extra)

Special thanks to @fresheyeball for explaining this shit to me


Setup

npm install
npm start

Quick Fly-By at Applicatives

So we know how Maybe works--it's a Just a or Nothing.

a in Just a can be a function.

To go from a Just 1 to a Just 3 we'd use map

Maybe.map ((+) 2) (Just 1) == Just 3
--=> True

So what happens if we had a Just (+) with the addition infix operator... how do we use this to add in an applicative manner to add Just 1 and Just 2?


Applicatives have 2 properties:

  • pure, singleton

  • apply, ap, <*>

Pure lets us know how to create a singleton list of for the default case of some applicative. Examples:

  • Maybe - Just

  • List - flip (::) []

And the ability to apply values in.


So what is Just (+)?

foo : Maybe (number -> number -> number)
foo =
    Just (+)

So let's use apply

import Maybe.Extra as Maybe


bar : Maybe (number -> number)
bar =
    foo `Maybe.andMap` Just 1

And let's apply the value to completely

baz : Maybe Int
baz =
    bar `Maybe.andMap` Just 2

isJust3 : Bool
isJust3 =
    baz == Just 3
--=> True
{-| Would be cool if we had Maybe.Extra.singleton -}
singleton : a -> Maybe a
singleton =
    Just

infixl 2 =>
(<*>) : Maybe (a -> b) -> Maybe a -> Maybe b
(<*>) =
    Maybe.andMap

isNothing : Bool
isNothing =
    singleton (+) <*> Just 1 <*> Nothing == Nothing
--=> True

Look at the the demo MaybeApplicative.elm.


So where have we seen a something like this?

foo' : number -> number -> number
foo' x y =
    x * y


foo'' : number -> number
foo'' =
    foo' 1

is function application ;)


So how does this relate to Json Decoders?

In Json.Decode.Extra:

apply : Decoder (a -> b) -> Decoder a -> Decoder b
(|:) : Decoder (a -> b) -> Decoder a -> Decoder b

Well that's obviously apply...

And in Json.Decode:

succeed : a -> Decoder a

Looks pretty pure to me...


So let's apply (heh heh) our knowledge

Create some dummy JSON string

coolJson : String
coolJson =
    """[
  {
    "foo": 0,
    "bar": true
  },
  {
    "foo": 1,
    "bar": true
  },
  {
    "foo": 2,
    "bar": false
  }
]
"""

Create some type alias to represent these cool data items

type alias CoolItem =
    { foo : Int
    , bar : Bool
    }

Let's create a decoder using applicative.

Reminder: the constructor for CoolItem is (Int -> Bool -> CoolItem)

So, Decode.succed CoolItem is Decoder (Int -> Bool -> CoolItem)

Also, lets forget Json.Decode.objectNs don't exist because they don't scale infinity whereas the applicatives do.

import Json.Decode as Decode exposing ((:=))


coolItemDecoder : Decoder CoolItem
coolItemDecoder =
    Decode.succeed CoolItem
        |: ("foo" := Decode.int)
        |: ("bar" := Decode.bool)

(:=) : String -> Decoder a -> Decoder a

So this := infix operator is used to apply the given decoder given a string for key JSON object (e.g. "foo" will be decoded as an integer).

So what happens when when apply in our foo decoder?

Well let's look at some types:

import Json.Decode as Decode exposing (Decoder, (:=))
import Json.Docode.Extra as Decode ((|:))


baz : Decoder (Int -> Bool -> CoolItem)
baz =
  Decode.succeed CoolItem


qux : Decoder (Bool -> CoolItem)
qux =
  Decode.succeed CoolItem
    |: ("foo" := Decode.int)


-- And the full decoder
coolItemDecoder : Decoder CoolItem
coolItemDecoder =
    Decode.succeed CoolItem
        |: ("foo" := Decode.int)
        |: ("bar" := Decode.bool)

So all we have to do now is set up our app to decode the JSON

import Html exposing (Html, text)


view : a -> Html String
view =
    text << toString


main : Html String
main =
    coolJson
        |> Decode.decodeString (Decode.list coolListDecoder)
        |> view

Decode.decodeString : Decoder a -> String -> Result String a

Decode.list : Decoder a -> Decoder (List a)

But, go look at the demo.


So how do we find Applicatives in a language like Elm without higher-kinded types? Look for type signatures and certain names or think about what the singleton would be.

In Elm you'll see the term singleton for pure. ...And most of the time you'll see andMap, ap, or apply.


So let's see some in action -- see Pokémon example.

elm-applicatives-and-json-decoders's People

Contributors

toastal avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.