Spent a whole day in rural Rwanda, watching - in action - an @elmlang web-app with a #Drupal backend we've built for @ihanganeproject.
— Amitai Burstein (@amitaibu) November 14, 2019
No marketing landing pages, no sale funnels, no targeted ads. Just a web-app that helps provide a better health care to mothers and their babies pic.twitter.com/PnLqV0vpSQ
module Counter exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
-- MODEL
type alias Model =
Int
emptyModel : Model
emptyModel =
0
-- UPDATE
type Msg
= Decrement
| Increment
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
Decrement ->
( model - 1
, Cmd.none
)
Increment ->
( model + 1
, Cmd.none
)
-- VIEW
view : Model -> Html Msg
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (toString model) ]
, button [ onClick Increment ] [ text "+" ]
]
type alias Recipe =
{ title: String
, image : String
, preparationTime: Int
}
type Bool = False | True
type DifficultyLevel
= Easy
| Normal
| Hard
type alias Recipe =
{ title: String
, image : String
, preparationTime: Int
, difficultyLevel : DifficultyLevel
}
type alias Recipe =
{ title: String
, ..
, isCarnivore : Bool
, isVegetarian : Bool
, isVegan : Bool
}
iAmConfused : Recipe
iAmConfused =
{ title = "A vegan steak?!"
, ..
, isCarnivore = True
, isVegetarian = False
, isVegan = True
}
type DietaryRestriction
= Carnivore
| Vegetarian
| Vegan
type alias Recipe =
{ title: String
, ..
, dietaryRestriction : DietaryRestriction
}
thatIsBetter : Recipe
thatIsBetter =
{ title = "A vegan steak!"
, ..
, dietaryRestriction = Vegan
}
type alias Recipe = { title: String , .. , preparationTime : Int , cookingTime : ? }
{ title: "foo" , preparationTime: 10, , cookingTime: null }
type alias Recipe =
{ title: String
, ..
, preparationTime : Int
, cookingTime : Maybe Int
}
iceCream : Recipe
iceCream =
{ title = "Ice Cream"
, ..
, preparationTime = 10
, cookingTime = Nothing
}
pizza : Recipe
pizza =
{ title = "Pizza"
, ..
, preparationTime = 10
, cookingTime = Just 15
}
type PreparationTimes
= NoPreparation
| Preparation Int (Maybe Int)
type alias Recipe =
{ title: String
, ..
, preparationTimes : PreparationTimes
}
iceCreamFromRefrigerator : Recipe
iceCreamFromRefrigerator =
{ title = "Ice Cream for lazy people"
, ..
, preparationTimes = NoPreparation
}
pizza : Recipe
pizza =
{ title = "Pizza"
, ..
, preparationTimes = Preparation 10 (Just 15)
}
type PreparationTimes
= NoPreparation
| Preparation Int (Maybe Int)
viewPreparationTimes : Recipe -> Html msg
viewPreparationTimes recipe =
case recipe.preparationTimes of
NoPreparation ->
text "No preparation required"
Preparation time Nothing ->
text "Takes " ++ (String.fromInt time) ++
"minutes, but no cooking"
Preparation time (Just cookingTime) ->
text "Takes " ++ (String.fromInt time) ++
" minutes and " ++ (String.fromInt cookingTime) ++
" minutes for cooking"
type WebData a
= NotAsked
| Loading
| Failure Http.Error
| Success a
type alias Recipe =
{ title: String
, ..
, preparationTimes : WebData PreparationTimes
}
viewPreparationTimes : Recipe -> Html msg
viewPreparationTimes recipe =
case recipe.preparationTimes of
Failure error ->
text "Error loading"
Success preparationTimes ->
case preparationTimes of
NoPreparation ->
text "No preparation required"
-- ..
_ ->
text "Loading ..."
type alias Ingredient =
{ name: String
, price : Int
}
type alias Recipe =
{ title: String
, ..
, ingredients : List Ingredient
}
viewIngredients : Recipe -> Html msg
viewIngredients recipe =
ul
[]
[ List.map
( \ingredient -> li [] [ text ingredient.name ] )
recipe.ingredients
]
viewTotalPrice : Recipe -> Html msg
viewTotalPrice recipe =
List.foldl
( \ingredient accum -> accum + ingredient.price )
0
recipe.ingredients