elm Inventory.Elm

Inventory.Elm
module Inventory exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)


-- MODEL


type alias Vendor =
    { name : String
    , email : String
    , items : List VendorItem
    }



-- the target is the number that should always be the onhand inventory in store.
-- the user uses the number input field to send what is on hand, and the target
-- helps determine how much needs to be ordered.
-- example: the target number for Mini 4 1/2 tortilla is 10. If there are 5 onhand, the
-- user puts that in the input and the target in the order becomes 5.


type alias ItemId =
    Int


type alias ItemTarget =
    Int


type alias UpdatedItemTarget =
    Int


type alias VendorItem =
    { id : Int
    , name : String
    , target : Int
    }


initialVendor : Vendor
initialVendor =
    { name = "Diane's"
    , email = "tortillas@dianes.com"
    , items = initialItems
    }


initialItems : List VendorItem
initialItems =
    [ VendorItem 1 "Mini 4 1/2" 10
    , VendorItem 2 "XL Burrito" 9
    , VendorItem 3 "Chip" 5
    , VendorItem 4 "6 Inch Corn" 12
    , VendorItem 5 "Snack Flour" 30
    ]


order : Vendor
order =
    { name = initialVendor.name
    , email = initialVendor.email
    , items = initialItems
    }



-- UPDATE


type Msg
    = UpdateInventory ItemId ItemTarget UpdatedItemTarget


update : Msg -> Vendor -> Vendor
update msg model =
    case msg of
        UpdateInventory value id target ->
            let
                updateOnHand e =
                    --
                    if e.id == id then
                        { e | target = (target - e.target) }
                    else
                        e
            in
                { order | items = List.map updateOnHand order.items }



-- VIEW
-- takes in string, returns a Html msg, which can receive
-- messages from onClick events


appName : String -> Html Msg
appName name =
    Html.h2 [ class "title" ] [ Html.text name ]


viewVendorItem : VendorItem -> Html Msg
viewVendorItem vendorItem =
    li []
        [ text vendorItem.name
        , input [ type_ "number", onInput (UpdateInventory vendorItem.id vendorItem.target) ]
        ]


viewOrderForm : List VendorItem -> Html Msg
viewOrderForm vendorItems =
    vendorItems
        |> List.map viewVendorItem
        |> ul []


view : Vendor -> Html Msg
view vendor =
    div [ class "content" ]
        [ appName "Inventory App"
        , viewOrderForm vendor.items
        , div [ class "button-group" ]
            [ button [] [ text "Order" ] ]
        ]


main : Program Never Vendor Msg
main =
    Html.beginnerProgram
        { model = initialVendor
        , view = view
        , update = update
        }

elm JSON解码

JSON解码

JsonDecode.elm

-- json : String
-- json =
--     """
-- {
--   "kind": "Listing",
--   "data": {
--     "children": [
--       {"data":{"url":"http://www.example.com", "title":"hello"}},
--       {"data":{"url": "http://www.example.com", "title":"world"}}
--     ]
--   }
-- }
-- """


type alias Post =
    { url : String
    , title : String
    }


type alias PostList =
    List Post


postDecoder : Decoder Post
postDecoder =
    JD.map2 Post
        (field "url" string)
        (field "title" string)



-- postsDecoder : Decoder PostList
-- postsDecoder =
--     at [ "data", "children" ] <|
--         JD.list <|
--             at [ "data" ] postDecoder


postsDecoder : Decoder PostList
postsDecoder =
    at [ "data" ] postDecoder
        |> JD.list
        |> at [ "data", "children" ]

elm 在Elm 0.18中反应'选择'

在Elm 0.18中反应'选择'

Main.elm
module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (id, value)
import Json.Decode as Json exposing (Decoder, string, at)
import Html.Events exposing (on)


main =
    beginnerProgram
        { model = model
        , update = update
        , view = view
        }



-- TYPES


type alias SelectItem =
    { value : String
    , text : String
    }


type alias Model =
    { message : String
    , selectOne : List SelectItem
    , selectTwo : List SelectItem
    , selectedOneValue : String
    , selectedTwoValue : String
    }


type Msg
    = ChangeMeal String
    | ChangeTime String



-- MODEL
-- Normally, we have an init, subscriptions, etc. but for simplicity, this uses
-- the beginner program.


model : Model
model =
    { message = "Select an item!"
    , selectOne =
        [ SelectItem "time-period-na" "--"
        , SelectItem "time-period-all" "All time"
        , SelectItem "time-period-week" "One Week"
        , SelectItem "time-period-24h" "24h"
        ]
    , selectTwo =
        [ SelectItem "fish" "The Salmon"
        , SelectItem "chicken" "Le Poulet"
        , SelectItem "stew" "Beef Bourguignon"
        , SelectItem "vegetarian" "Vegetable Terrine"
        ]
    , selectedOneValue = "time-period-na"
    , selectedTwoValue = "fish"
    }



-- returns a zero-indexed integer of selected. Not so useful! Boo!


onSelectIndex : (Int -> msg) -> Html.Attribute msg
onSelectIndex message =
    on "change" <| Json.map message <| Json.at [ "target", "selectedIndex" ] Json.int



-- returns the value of the target value. More useful! Yay!
-- (e.g. this is what would be returned if you submitted a form)


onSelectValue : (String -> msg) -> Attribute msg
onSelectValue message =
    Json.at [ "target", "value" ] Json.string
        |> Json.map message
        |> Html.Events.on "change"



-- UPDATE


update : Msg -> Model -> Model
update msg model =
    case msg of
        ChangeTime value ->
            { model | selectedOneValue = value }

        ChangeMeal value ->
            { model | selectedTwoValue = value }



-- VIEW


viewSelect : List SelectItem -> List (Html Msg)
viewSelect itemList =
    itemList
        |> List.map
            (\item ->
                option [ value item.value ] [ text item.text ]
            )


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text "Reactive 'select' in Elm 0.18!" ]
        , h3 [] [ text "See? Not so hard ;)" ]
        , p [] [ text model.message ]
        , select [ onSelectValue ChangeTime ] (viewSelect model.selectOne)
        , p [] [ text ("You selected item with value == " ++ model.selectedOneValue) ]
        , select [ onSelectValue ChangeMeal ] (viewSelect model.selectTwo)
        , p [] [ text ("You selected item with value == " ++ model.selectedTwoValue) ]
        ]

elm GenServer.elm

otp.elm
module GenServer exposing (genserver)

type alias GenServer a model msg =
  { send : a
  , init : model
  , update : Pid -> model -> msg -> (model, Cmd msg)
  }
  
singleton : GenServer (Cmd a) model msg -> 

regular : Genserver (Pid -> Cmd a) model msg
GenServer.elm
module GlobalCounter exposing (..)

type alias Model = Int
type Msg 
  = Increment
  | Decrement
  | Reset
  | GetState Pid

main =
  GenServer.singleton 
    { init = init
    , send = send
    , update = update
    }

send : msg -> 
  
init : a -> Model
init = 0

update : Pid -> Model -> Message -> (Model, Cmd)
handleCast self state msg =
  case msg of
    Increment -> 
      state + 1 ! []
    Decrement -> 
      state - 1 ! []
    Reset ->
      0 ! []
    GetState from ->
      state ! [ Process.send from state ]
      
  

elm Elmchemy文章#2

Elmchemy文章#2

fizbuzz.elm
module FizzBuzz exposing (fizzbuzz)

import List exposing (map, range)

{-| Fizzes the buzzes and buzzfizzes the fizz out of buzz

    fizzbuzz 1 7 == "1 2 Fizz 4 Buzz Fizz 7"
-}
fizzbuzz : Int -> Int -> String
fizzbuzz from to = 
  let fizzBuzz n = case (n % 3, n % 5) of
    (0, 0) -> "FizzBuzz"
    (0, _) -> "Fizz"
    (_, 0) -> "Buzz"
    _      -> toString n
  in List.range from to |> map (fizzBuzz >> toString) |> joinWords
  
  
joinWords : List String -> String
joinWords list = String.join " " list

elm zipper.elm

zipper.elm
module Main exposing (..)

import Html exposing (text)
import MultiwayTree exposing (..)
import MultiwayTreeZipper exposing (..)
import Dict exposing (Dict)


type alias StrTree =
    Tree String


type alias KeyedStr =
    { key : Int, word : String }


type alias KeyedStrTree =
    Tree KeyedStr


type alias TreeZipper =
    Zipper KeyedStr


type alias Route =
    List Int


type alias BreadIndex =
    Dict Int Route



-- (&>) =
--   flip Maybe.map


main : Html.Html msg
main =
    text <| toString <| (flip Maybe.map createEmpZipper createBreadIndex)



-- (a, 0), (b, 1), (c, 4), (d, 2), (e, 3), (f, 5), (g, 6)
-- (0, []), (1, [0]), (2, [0, 0]), (3, [0, 1]), (4, [1]), (5, [1, 0]), (6, [1, 1])


base : StrTree
base =
    Tree "a"
        [ (Tree "b"
            [ Tree "d" [], Tree "e" [] ]
          )
        , (Tree "c"
            [ Tree "f" [], Tree "g" [] ]
          )
        ]


keyedStrTree : StrTree -> Maybe KeyedStrTree
keyedStrTree =
    indexedMap (\k w -> { key = k, word = w })


createEmpZipper : Maybe TreeZipper
createEmpZipper =
    Maybe.map (\t -> ( t, [] )) (base |> keyedStrTree)


createBreadIndex : TreeZipper -> ( TreeZipper, BreadIndex )
createBreadIndex (( tree, bc ) as tz) =
    let
        dict =
            createBreadIndex_ Dict.empty [] tree
    in
        ( tz, dict )


createBreadIndex_ : BreadIndex -> List Int -> KeyedStrTree -> BreadIndex
createBreadIndex_ dict cur tree =
    case tree of
        Tree v [] ->
            Dict.insert v.key cur dict

        Tree v forest ->
            let
                newDict =
                    Dict.insert v.key cur dict
            in
                createBreadIndex__ -1 cur newDict forest


createBreadIndex__ : Int -> List Int -> BreadIndex -> Forest KeyedStr -> BreadIndex
createBreadIndex__ idx parent dict forest =
    case forest of
        [] ->
            dict

        t :: ts ->
            case t of
                Tree v [] ->
                    let
                        curId =
                            idx + 1

                        cur =
                            parent ++ [ curId ]

                        newDict =
                            Dict.insert v.key cur dict
                    in
                        createBreadIndex__ (idx + 1) cur newDict ts

                Tree v tss ->
                    let
                        curId =
                            idx + 1

                        cur =
                            parent ++ [ curId ]

                        newDict =
                            Dict.insert v.key cur dict

                        curDict =
                            createBreadIndex__ (idx + 1) parent newDict ts

                        curcurDict =
                            createBreadIndex__ -1 parent newDict tss
                    in
                        Dict.union curDict curcurDict

elm counter.elm

counter.elm
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)


{-| Entry point
-}
main =
  Html.beginnerProgram { model = model, view = view, update = update }



{-| Model
-}
type alias Model = Int

model : Model
model =
  0


{-| Update
-}
type Msg = Increment | Decrement

update : Msg -> Model -> Model
update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1


{-| View
-}
view : Model -> Html Msg
view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick Increment ] [ text "+" ]
    ]

elm listZipper.elm

listZipper.elm
import Html exposing (..)
import Debug

main = let
           xs = [1, 2, 3, 4]
           zippers = [
               goForward (xs, []),
               goForward ([2, 3, 4], [1]),
               goForward ([3, 4], [2, 1]),
               goBack ([4], [3, 2, 1])
               ]
           zippersLi = zippers |> List.map toString |> List.map (\s -> li [] [ text s ] )
       in
          ul [] zippersLi

type alias ListZipper a = (List a, List a)

goForward : ListZipper a -> ListZipper a
goForward (list, bs) =
    case list of
        (x::xs) -> (xs, x::bs)
        _       -> Debug.crash "Can't move forward"

goBack : ListZipper a -> ListZipper a
goBack (xs, bs) =
    case bs of
        (b::bss) -> (b::xs, bss)
        _        -> Debug.crash "Can't move back"

elm zipper.elm

zipper.elm
import Html exposing (..)
import Debug

main = text <| toString newTree

newTree = (freeTree, []) |> goLeft |> goRight |> modify (\_ -> 'P') |>
          attach (Node 'Z' Empty Empty) |> goUp |> modify (\_ -> 'X') |> topMost

type Tree a = Empty | Node a (Tree a) (Tree a)

freeTree : Tree Char
freeTree =
    Node 'P'
        (Node 'O'
            (Node 'L'
                    (Node 'N' Empty Empty)
                    (Node 'T' Empty Empty)
            )
            (Node 'Y'
                    (Node 'S' Empty Empty)
                    (Node 'A' Empty Empty)
            )
        )
        (Node 'L'
            (Node 'W'
                (Node 'C' Empty Empty)
                (Node 'R' Empty Empty)
            )
            (Node 'A'
                (Node 'A' Empty Empty)
                (Node 'C' Empty Empty)
             )
        )

type Direction = L | R
type alias Directions = List Direction

changeToP : Directions -> Tree Char -> Tree Char
changeToP dir tree =
    case (dir, tree) of
        ( L::ds, Node x l r ) -> Node x (changeToP ds l) r
        ( R::ds, Node x l r ) -> Node x l (changeToP ds r)
        ( [],    Node _ l r ) -> Node 'P' l r
        _                     -> Debug.crash "Can't change to P!"

elemAt : Directions -> Tree a -> Maybe a
elemAt dir tree =
    case (dir, tree) of
        ( L::ds, Node _ l _ ) -> elemAt ds l
        ( R::ds, Node _ _ r ) -> elemAt ds r
        ( []   , Node x _ _ ) -> Just x
        _                     -> Nothing


type Crumb a = LeftCrumb a (Tree a)
             | RightCrumb a (Tree a)

type alias Breadcrumbs a = List (Crumb a)

type alias Zipper a = (Tree a, Breadcrumbs a)

goLeft : Zipper a -> Zipper a
goLeft (tree, bs) =
    case (tree, bs) of
        ( Node x l r, bs) -> ( l, LeftCrumb x r::bs )
        _                 -> Debug.crash "Doesn't exist Left"

goRight : Zipper a -> Zipper a
goRight (tree, bs) =
    case (tree, bs) of
        ( Node x l r, bs) -> ( r, RightCrumb x l::bs )
        _                 -> Debug.crash "Doesn't exist Right"

goUp : Zipper a -> Zipper a
goUp (tree, bs) =
    case (tree, bs) of
        (t, LeftCrumb  x r::bs) -> (Node x t r, bs)
        (t, RightCrumb x l::bs) -> (Node x l t, bs)
        _                       -> Debug.crash "Doesn't exist Up"

modify : (a -> a) -> Zipper a -> Zipper a
modify f (tree, bs) =
    case (tree, bs) of
        (Node x l r, bs) -> (Node (f x) l r, bs)
        (Empty, bs)      -> (Empty, bs)

attach : Tree a -> Zipper a -> Zipper a
attach t (_, bs) = (t, bs)

topMost : Zipper a -> Zipper a
topMost ((tree, bs) as z) =
    case z of
        (t, []) -> (t, [])
        z       -> topMost (goUp z)

elm fizzbuzz

fizzbuzz

main.elm
module Main exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)

main =
    beginnerProgram
      { model = model,
        update = update,
        view = view
      }

-- MODEL

type alias Model =
    { max: Int,
      fizz: Int,
      buzz: Int
    }

model : Model
model = { max = 100, fizz = 3, buzz = 5 }

-- UPDATE

type Msg
   = Max String
   | Fizz String
   | Buzz String

update : Msg -> Model -> Model
update msg model =
  case msg of
    Max max   ->
      { model | max  = Result.withDefault 0 (String.toInt max)  }
    Fizz fizz ->
      { model | fizz = Result.withDefault 0 (String.toInt fizz) }
    Buzz buzz ->
      { model | buzz = Result.withDefault 0 (String.toInt buzz) }

-- VIEW

view : Model -> Html Msg
view model =
  div [] [
    div [class "fizzbuzzInputs"]
    [
      maxView model.max,
      fizzbuzzInputView model.fizz model.buzz
    ],
    fizzbuzzView model
  ]

maxView : Int -> Html Msg
maxView max =
    input [ type_ "number", value (toString max), onInput Max ] []

fizzbuzzInputView : Int -> Int -> Html Msg
fizzbuzzInputView fizz buzz =
  div [ class "fizzbuzzInputs" ] [
    div [ id "fizzContainer" ] [
      label [] [text "Fizz"],
      input [ type_ "number", value (toString fizz), onInput Fizz ] []
    ],
    div [ id "buzzContainer" ] [
      label [] [text "Buzz"],
      input [ type_ "number", value (toString buzz), onInput Buzz ] []
    ]
  ]

fizzbuzzView : Model -> Html msg
fizzbuzzView model =
  let
    fizzbuzzElm n = li [ ] [ text n ]
    fizzbuzzElms =
      fizzbuzz model.max model.fizz model.buzz |>
      List.map fizzbuzzElm
  in
    ul [ class "fizzBuzzList" ] fizzbuzzElms

fizzbuzz : Int -> Int -> Int -> List String
fizzbuzz max fizz buzz =
  let
    fizzbuzzStr n =
      case (n % fizz, n % buzz) of
        (0, 0) -> "FizzBuzz"
        (0, _) -> "Fizz"
        (_, 0) -> "Buzz"
        _      -> toString n
  in
    List.range 1 max |>
    List.map fizzbuzzStr