Posted by FullyForged on Thu, 01/21/2016 - 12:30

When working with Phoenix channels and Elm it may be useful to keep track of the websockets connection status. In this blog post, we’ll see how this can be accomplished by leveraging interoperability.

Posted by dennisreimann on Tue, 01/19/2016 - 02:00

Importing a module exposes its functionality in the context of the program that is loading the module. In Elm there are different ways to import modules and we will have a look at these in this article.

Posted by Rundis on Tue, 01/19/2016 - 01:00

Any serious Single Page Application needs to have routing. Right ? So before we add
any further pages it’s time to add routing support to the Elm frontend.

In episode 2, we implemented
a Micky Mouse solution for page routing. Clearly that approach won’t scale. Now is a good time to
implement something that can handle multiple pages, history navigation, direct linking etc.
We could do it all from scratch, but lets opt for pulling in a library.
In this episode we’ll introduce elm-transit-router
to the Albums sample application.

Useful resources

  • Check out the other episodes in this blog series.
  • The accompanying Albums sample app is on github, and there is a tag
    for each episode

Introduction

I decided pretty early on to try out the elm-transit-router library.
It seemed to cover most of what I was looking for. It even has some pretty cool support for animations when doing page transitions.

Static typing is supposed to be really helpful when doing refactoring. Introducing routing should be a nice little excersize to
see if that holds. Remember, there still isn’t a single test in our sample app, so it better hold.
The elm-transit-router library github repo contains a great example app that proved very helpful
in getting it up and running for the Albums app.

Hop is an alternative routing library you might want to check out too.

Implementation changes

frontend/elm-package.json

// (...
"source-directories": [
".",
"src/" (1)
],

// ...
"dependencies": {
//... others ommitted
"etaque/elm-route-parser": "2.1.0 <= v < 3.0.0", (2)
"etaque/elm-transit-style": "1.0.1 <= v < 2.0.0", (3)
"etaque/elm-transit-router": "1.0.1 <= v < 2.0.0" (4)

}
...

1
We’ve moved all elm files but Main.elm to the a src sub directory. So we need to add src to the list of source directories

2
A typed route parser with a nice DSL in Elm: We use it for defining our routes

3
Html animations for elm-transit

4
Drop-in router with animated route transitions for single page apps in Elm. Drop in, as in fitting very nicely with elm start-app.

Album dependencies
Click for larger diagram

The addition of the 3 new dependencies also adds quite a few transitive dependencies. The diagram
above is automatically generated by the elm-light plugin for Light Table.

Defining routes (frontend/src/Routes.elm)

type Route (1)
= Home
| ArtistListingPage
| ArtistDetailPage Int
| NewArtistPage
| EmptyRoute

routeParsers : List (Matcher Route)
routeParsers =
[ static Home "/" (2)
, static ArtistListingPage "/artists"
, static NewArtistPage "/artists/new"
, dyn1 ArtistDetailPage "/artists/" int "" (3)
]

decode : String -> Route
decode path = (4)
RouteParser.match routeParsers path
|> Maybe.withDefault EmptyRoute

encode : Route -> String
encode route = (5)
case route of
Home -> "/"
ArtistListingPage -> "/artists"
NewArtistPage -> "/artists/new"
ArtistDetailPage i -> "/artists/" ++ toString i
EmptyRoute -> ""

1
Union type that defines the different routes for the application

2
A static route matcher (static is a function from the RouteParser dsl)

3
Dynamic route matcher with one dynamic param

4
We try to match a given path with the route matchers defined above. Returns route of first successful match, or the EmptyRoute route
if no match is found.

5
Encode a given route as a path

A few handy router utils (frontend/src/Routes.elm)

redirect : Route -> Effects ()
redirect route = (1)
encode route
|> Signal.send TransitRouter.pushPathAddress
|> Effects.task

clickAttr : Route -> Attribute
clickAttr route = (2)
on "click" Json.value (\_ -> Signal.message TransitRouter.pushPathAddress <| encode route)

linkAttrs : Route -> List Attribute
linkAttrs route = (3)
let
path = encode route
in
[ href path
, onWithOptions
"click"
{ stopPropagation = True, preventDefault = True }
Json.value
(\_ -> Signal.message TransitRouter.pushPathAddress path)
]

1
This function allows us to perform routing through a redirect kind of effect. Comes in handy when we need to switch
routes as a result of performing a task or doing an update action of some sort.

2
Helper function that creates a click handler attribute. When clicked the signal is forwarded to an address of the internal mailbox for the
elm-transit-router library. By means of delegation the internal TransitRouter.Action type is wrapped into our app’s Action type.
We’ll get back to this when we wire it all together !

3
Another helper function, similar to clickAttr, but this is more specific for links that also has a href attribute

Changes in Main.elm

Too hook in elm-transit-router we need to make a couple of changes to how we wire up our model, actions, view and update function.
It’s also worth noting that from episode 2 have removed all direct update delegation from ArtistListing to ArtistDetail, this now
all will happen through route transitions. An immediate benefit of that is that the ArtistDetail page becomes much reusable.

Model, actions, transitions and initialization

type alias Model = WithRoute Routes.Route (1)
{ homeModel : Home.Model
, artistListingModel : ArtistListing.Model
, artistDetailModel : ArtistDetail.Model
}

type Action =
NoOp
| HomeAction Home.Action
| ArtistListingAction ArtistListing.Action
| ArtistDetailAction ArtistDetail.Action
| RouterAction (TransitRouter.Action Routes.Route) (2)

initialModel : Model
initialModel =
{ transitRouter = TransitRouter.empty Routes.EmptyRoute (3)
, homeModel = Home.init
, artistListingModel = ArtistListing.init
, artistDetailModel = ArtistDetail.init
}

actions : Signal Action
actions =
Signal.map RouterAction TransitRouter.actions (4)

mountRoute : Route -> Route -> Model -> (Model, Effects Action)
mountRoute prevRoute route model = (5)
case route of

Home ->
(model, Effects.none)

ArtistListingPage -> (6)
(model, Effects.map ArtistListingAction (ServerApi.getArtists ArtistListing.HandleArtistsRetrieved))

ArtistDetailPage artistId ->
(model, Effects.map ArtistDetailAction (ServerApi.getArtist artistId ArtistDetail.ShowArtist))

NewArtistPage ->
({ model | artistDetailModel = ArtistDetail.init } , Effects.none)

EmptyRoute ->
(model, Effects.none)

routerConfig : TransitRouter.Config Routes.Route Action Model
routerConfig = (7)
{ mountRoute = mountRoute
, getDurations = \_ _ _ -> (50, 200)
, actionWrapper = RouterAction
, routeDecoder = Routes.decode
}

init : String -> (Model, Effects Action)
init path = (8)
TransitRouter.init routerConfig path initialModel

1
We extend our model using WithRoute for our Route type in routes. This extends our type with a transitRouter property

2
We add a RouteAction to our Action type. We will handle that explicitly in the update function we’ll cover in the next section

3
We define an initial model, which has the initial models for the various pages. In addition we initialize the transitRouter property
with an empty state and EmptyRoute route (that didn’t read to well). Basically a route that shouldn’t render anything, because it will transition
to an actual route. It’s just an intermediary

4
Transformer for mapping TransitRouter actions to our own RouterAction. This allows start-app to map external input signals to inputs with an action type our application
can recognize and process.

5
mountRoute is a function that provides what we want to happen in our update when a new route is mounted. Currently we
only pattern match on route to be mounted, but we could also match on the combination of previous route and new route to provide
custom behaviour depending on where you came from and where your are going to. Very powerful !

6
When the ArtistListingPage route is mounted we return an effect to retrieve artists (when that effect returns the ArtistListing.HandleArtistRetrieved action is then eventually passed to the update function of ArtistListing)

7
routerConfig wires together the various bits that TransitRouter needs to do it’s thing

8
The init function now just initializes the TransitRouter with our config, and initial path (which we receive from a port) and our Initial model

There’s quite a bit going on here, but once this is all in place, adding new routes is quite a breeze. I’d recommend reading
through the Readme for elm-transit-router to understand more about the details of each step

The update function

update : Action -> Model -> (Model, Effects Action)
update action model =
case action of

NoOp ->
(model, Effects.none)

HomeAction homeAction ->
let (model', effects) = Home.update homeAction model.homeModel
in ( { model | homeModel = model' }
, Effects.map HomeAction effects )

ArtistListingAction act -> (1)
let (model', effects) = ArtistListing.update act model.artistListingModel
in ( { model | artistListingModel = model' }
, Effects.map ArtistListingAction effects )

ArtistDetailAction act -> (2)
let (model', effects) = ArtistDetail.update act model.artistDetailModel
in ( { model | artistDetailModel = model' }
, Effects.map ArtistDetailAction effects )

RouterAction routeAction -> (3)
TransitRouter.update routerConfig routeAction model

1
You should recognize this pattern from the previous episode. We delegate all actions tagged with ArtistListingAction
to the update function for ArtistListing. The we update the model with the updated model from ArtistListing and
map any effects returned.

2
If you remember from episode 2 this used to reside in ArtistListing, but
has been moved here.

3
RouterAction action types are handled by the update function in TransitRouter. If you Debug.log this function you will see this
is called repeadly when there is a transition from one route to the next. (To handle the animation effects most notably)

The main view/layout

menu : Signal.Address Action -> Model -> Html
menu address model = (1)
header [class "navbar navbar-default"] [
div [class "container"] [
div [class "navbar-header"] [
div [ class "navbar-brand" ] [
a (linkAttrs Home) [ text "Albums galore" ]
]
]
, ul [class "nav navbar-nav"] [
li [] [a (linkAttrs ArtistListingPage) [ text "Artists" ]] (2)
]
]
]

contentView : Signal.Address Action -> Model -> Html
contentView address model = (3)
case (TransitRouter.getRoute model) of
Home ->
Home.view (Signal.forwardTo address HomeAction) model.homeModel

ArtistListingPage -> (4)
ArtistListing.view (Signal.forwardTo address ArtistListingAction) model.artistListingModel

ArtistDetailPage i ->
ArtistDetail.view (Signal.forwardTo address ArtistDetailAction) model.artistDetailModel

NewArtistPage ->
ArtistDetail.view (Signal.forwardTo address ArtistDetailAction) model.artistDetailModel

EmptyRoute ->
text "Empty WHAT ?"

view : Signal.Address Action -> Model -> Html
view address model =
div [class "container-fluid"] [
menu address model
, div [ class "content"
, style (TransitStyle.fadeSlideLeft 100 (getTransition model))] (5)
[contentView address model]
]

1
Menu view function for the app

2
Here we use the linkAttrs util function from Routes.elm to get a click handler. When the link is click
a route transition to the given page will occur (with addressbar update, history tracking and the whole shebang)

3
We render the appropriate main content view based which route is current in our model.

4
Getting the view for a page is used in the typical start-app way. Call the view function of the sub component and make sure
to provide a forwarding addres that main can handle in its update function !

5
We define the route transition animation using the style attribute (function) in elm-html. Here we use a transition style
defined in elm-transit-style.

How to navigate from one page to another ?

Move from artistlisting to artistdetail (frontend/src/ArtistListing.elm)

artistRow : Signal.Address Action -> Artist -> Html
artistRow address artist =
tr [] [
td [] [text artist.name]
,td [] [button [ Routes.clickAttr <| Routes.ArtistDetailPage artist.id ] [text "Edit"]] (1)
,td [] [button [ onClick address (DeleteArtist (.id artist))] [ text "Delete!" ]]
]

view : Signal.Address Action -> Model -> Html
view address model =
div [] [
h1 [] [text "Artists" ]
, button [
class "pull-right btn btn-default"
, Routes.clickAttr Routes.NewArtistPage (2)
]
[text "New Artist"]
, table [class "table table-striped"] [
thead [] [
tr [] [
th [] [text "Name"]
,th [] []
,th [] []
]
]
, tbody [] (List.map (artistRow address) model.artists)
]
]

1
For navigation using links we just use the util function Routes.clickAttr function we defined earlier. This will trigger the necessary
route transition to the appropriate page (with params as necessary)

2
It’s worth noting that we since episode 2 have introduced a separate route for handling NewArtist (/artists/new). We are still
using the same behaviour otherwise, so it’s just a minor modification to have a separate transition for a new artist (since that doesn’t have a numeric id as part of its route path)

Move to the artist listing after saving an artist (frontend/src/ArtistDetail.elm)

-- ... inside update function

HandleSaved maybeArtist ->
case maybeArtist of
Just artist ->
({ model | id = Just artist.id
, name = artist.name }
, Effects.map (\_ -> NoOp) (Routes.redirect Routes.ArtistListingPage) (1)
)

Nothing ->
Debug.crash "Save failed... we're not handling it..."

1
We use the Routes.redirect function we defined earlier. When the task fro saving is completed we trigger an effect
that will transtion route to the ArtistListing page. To allow the effect to work in our update function we need to map it to
an action that ArtistDetail knows about (we don’t have access to the RouterAction in main here!). That’s why we map the effect
to a NoOp action.

The final wiring

frontend/main.elm

app : StartApp.App Model
app =
StartApp.start
{ init = init initialPath (1)
, update = update
, view = view
, inputs = [actions] (2)
}

main : Signal Html
main =
app.html

port tasks : Signal (Task.Task Never ())
port tasks =
app.tasks

port initialPath : String (3)

1
We call the init function previously defined with a initialPath (which we get from a port, see 3 below)

2
The inputs fields of the start-app config is for external signals. We wire it to our actions defintion defined earlier

3
We get the initialPath through a port from JavaScript. See the next section for how

INFO: Initially I forgot to wire up the inputs. The net result of that was that none of the links actually did anything.
Was lost for a while there, but the author of elm-transit-router etaque was able to spot it easily
when I reached out in the elm-lang slack channel

frontend/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Albums</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
</head>
<body>
<script type="text/javascript" src="main.js"></script> (1)
<script type="text/javascript" src="/_reactor/debug.js"></script> (2)

<script type="text/javascript">
var main = Elm.fullscreen(Elm.Main, {initialPath: "/"}); (3)
</script>

</body>
</html>

1
This is the transpiled elm to js for our frontend app

2
We don’t really need this one, but if reactor in debug mode had worked with ports this would be necessary for debug tracing etc

3
We start our elm app with an input param for our initialPath. This is sent to the port defined above. It’s currently hardcoded to / (home), but
once we move to a proper web server we would probably use something like window.location.pathname to allow linking directly to
a specific route within our Single Page App.

Summary and next steps

This was an all Elm episode. Hopefully I didn’t loose all Haskellites along the way because of that. We’ve added a crucial
feature for any Single Page (Web) Application in this episode. The end result was pretty neat and tidy too.

So how was the refactoring experience this time ? Well the compiler was certainly my best buddy along the way. Obviously I also
had to consult the documentation of elm-transit-router quite often. i had a few times where things appeared to be compiling fine
in Light Table, but actually there was some error in a Module referred by Main. I’m not sure if it’s make’s fault or just that there is
something missing in the elm-light plugin. I’ll certainly look into that. Always handy to have the command line available when you’re
not sure about whether your IDE/Editor is tripping you up or not. I don’t think tests would have caught many of the issues I encountered.
Forgetting to wire up inputs to startapp was probably my biggest blunder, and I’m sure no test would have covered that. I needed to know that this
was something I had to wire up for it to work. RTFM etc.

Next up I think we will look at how much effort there is to add additional features. The hypothesis is that it should be
fairly straighforward, but who knows !

Posted by dennisreimann on Sun, 01/17/2016 - 02:00

How to install Elm and which tools do you need to build your first project? Besides clarifying these questions we will also look at a toolchain that goes beyond the simple Hello World.

Posted by codecentric on Sat, 01/16/2016 - 15:57

We have already touched the topic of Elm’s type system briefly (for example in post VI about type annotations) but Elm provides a few type constructs that we have not examined yet. We also talked about the advantages of having a strong type system, namely the stronger guarantees it enables as compared to dynamic languages like JavaScript. This boils down to “If it compiles, it’ll never throw a runtime exception”. In this episodes, we’ll revisit tuples and introduce type aliases and records.

About This Series
This is the ninth post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you have missed the previous episodes, you might want to check out the table of contents.
Tuples
We have already used tuples in previous examples but since they are one of the basic building blocks for types, let’s review the concept shortly.
Tuples are similar to lists as they represent collections of multiple items. However, in a list, all elements need to have the same type. The number of elements is variable. In contrast, the elements of a tuple can all have different types but all tuples of the same type have the same length.
Here are some examples for a tuples (representing human beings with a name, weight in kilograms and their height in meters):

alice : (String, Int, Float)
alice = ("Alice", 61, 1.68)

bob : (String, Int, Float)
bob = ("Bob", 78, 1.82)

So, tuples are pairs (or triplets, quadruplets, …) of values. They are enclosed in ( and ) in Elm.
You can use pattern matching to access individual parts of the tuple. The following function takes a 3-tuple like in the example above and returns the name by doing a pattern matching on the incoming tuple. Since we do not care about the weight and the height here, we use the underscore (_) for those values.
getName : (String, Int, Float) -> String
getName (name, _, _) = name
Type Aliases
You can assign type aliases to make your code more readable. If the first element of a tuple is meant to represent a name, why not call it just that?
type alias Name = String
type alias Weight = Int
type alias Height = Float

alice : (Name, Weight, Height)
alice = ("Alice", 61, 1.68)

bob : (Name, Weight, Height)
bob = ("Bob", 78, 1.82)
Here, we used type aliases for basic types that are provided by Elm out of the box. You can use type aliases for any type construct you like, as we’ll see later.
Records
Tuples are one way to represent data structures. They are best suited for structures with only a few attributes, like pairs of values. For more structured data, Elm offers an alternative called records. This is how records looks like:
type alias Person =
{ name : String
, weight : Int
, height : Float
}

alice : Person
alice =
{ name = "Alice"
, weight = 61
, height = 1.68
}

bob : Person
bob =
{ name = "Bob"
, weight = 78
, height = 1.82 }
Note how we used a type alias here to have an identifier for the record type. This identifier (Person) can be used in type annotations then. The two values alice and bob show how to create new records.
There are a few more things that you can do with records and we will get to that in the next sections.
Access Record Attributes
Record attributes are accessed using a dot notation. To access the name of a Person record, you would write person.name, or person.height to access the person’s height attribute.
The dot notation can even be used as a standalone function. This is valid Elm code which converts a list of Person records into a list of their names:
toNames : List Person -> List String
toNames list =
List.map .name list
Update Record Fields
Elm also provides a mechanism to update records. Since all values in Elm are immutable, “updating” a record translates to creating a copy of the original record and changing one (or several) attributes in the process.
The following example demonstrates how to update one attribute.
rename : Person -> String -> Person
rename person newName =
{ person | name = newName }
The next example updates multiple attributes at once.
grow : Person -> Int -> Float -> Person
grow person weightIncrease heightIncrease =
{ person |
weight = person.weight + weightIncrease,
height = person.height + heightIncrease }

That’s it for today. Now that we have reviewed tuples, type aliases and records, there is only one major type construct missing, which is called union types. This will be covered in the next episode. See you next time!
The post Elm Friday: Type System Basics – Type Aliases and Records (Part IX) appeared first on codecentric Blog.

Posted by Rundis on Thu, 01/14/2016 - 01:00

My journey into Elm and Haskell continues. It’s time to add database support.

Since episode 1 I’ve
managed to implement simple CRUD features for the Artist entity of the Albums sample application.
It’s been anything but plain sailing, but it’s been a blast so far. Trying to wrap my head around two
new languages and their libraries in parallell is somewhat daunting. The journey would probably
have been smoother if I took more time to learn the language proper. Learning by doing is at times
frustrating, at the same time very rewarding when stuff finally works.

There seems to be a pretty close correlation between it compiles and it works when programming
in Elm and Haskell

— Magnus
(yeah I know; correlation does not imply causation)

Table of Contents

Overview

Useful resources

  • Check out the other episodes in this blog series.
  • The accompanying Albums sample app is on github, and there is a tag
    for each episode

So what have I done for this episode ?

  • Added persistence support to the haskell/servant backend server using SQLite
  • REST API now supports POST, PUT, DELETE and GET (multiple/single) Artists
  • The Elm frontend has features for listing, deleting, updating and creating new artists

albumlistingpage

I’ve taken a bottom up approach to developing the features. For both the Frontend and the Backend I’ve
implemented everything in one module. After that I’ve done pretty substantial refactorings into smaller
modules while letting the respective compilers guide me along the way. So how did that work out ?

Backend

Pretty early on I managed to get halive to start working. Having live recompiling is
really nice and seriously improved my workflow. I have very limited editor support because my editor (Light Table)
currently doesn’t provide much in terms of haskell support. I was almost derailed with developing a Haskell plugin (or making the existing one work), but
managed to keep on track.

Adding cors support

During development of the spike for the previous episode I used a chrome plugin to get around CORS
restrictions from my browser. Surely this has to be solvable ? Indeed it was, wai-cors to the rescue.

backend/albums.cabal

build-depends:
-- ...
, wai-cors
-- ...

backend/src/Main.hs

;....

import Network.Wai.Middleware.Cors

;....

albumCors :: Middleware
albumCors = cors $ const (Just albumResourcePolicy) (1)

albumResourcePolicy :: CorsResourcePolicy (2)
albumResourcePolicy =
CorsResourcePolicy
{ corsOrigins = Nothing -- gives you /*
, corsMethods = ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTION"]
, corsRequestHeaders = simpleHeaders -- adds "Content-Type" to defaults
, corsExposedHeaders = Nothing
, corsMaxAge = Nothing
, corsVaryOrigin = False
, corsRequireOrigin = False
, corsIgnoreFailures = False
}

main :: IO ()
main = do
run 8081 $ albumCors $ app (3)

1
Define wai cors middleware

2
Define a cors policy. This one is very lax. You wouldn’t want to use this for anything public facing as is

3
Apply the middleware to our app. Now cross origin headers are added and OPTION prefligh requests are supported. Nice

Cors inspiration harvested from https://github.com/nicklawls/lessons btw

Enter SQLite

I looked at a few different options for database support. Most examples and tutorials related
to servant and database usage seems to favor persistent.
I’m surely going to have a closer look at that, but my initial impression was that perhaps there was just
a little bit to much going on there. Just a little bit to much "magic" ? Having lost my taste
for ORM’s in the JVM spehere (hibernate in particular) I wanted to start with something closer to the metal.

So to make it a little harder for myself I went for the sqlite-simple library.
Pretty happy with the choice so far.

backend/albums.cabal

build-depends:
-- ...
, sqlite-simple
-- ...

backend/Main.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where

import qualified Storage as S (1)
import qualified Api as A (2)
import Network.Wai
import Network.Wai.Handler.Warp
import Servant
import Network.Wai.Middleware.Cors
import Control.Exception (bracket)
import Database.SQLite.Simple as Sql

app :: Sql.Connection -> Application
app conn = serve A.api (A.artistsServer conn) (3)

testConnect :: IO Sql.Connection
testConnect = Sql.open ":memory:" (4)

withTestConnection :: (Sql.Connection -> IO a) -> IO a
withTestConnection cb = (5)
withConn $ \conn -> cb conn
where
withConn = bracket testConnect Sql.close (6)

{-
...
cors stuff omitted, already covered
-}

main :: IO ()
main = do
withTestConnection $ \conn -> do
S.bootstrapDB conn (7)
run 8081 $ albumCors $ app conn (8)

1
Module with functions for communication with the Albums database. Only used for bootstrapping with test data in main

2
Module that defines the webservice api

3
We make sure to pass a connection to our webservice server

4
For simplicity we are using an in memory database

5
Wrap a function (cb) giving it a connection and cleaning up when done

6
bracket ensures we also release the connection in case of any exceptions.

7
Creates schema and bootstraps with some sample data

8
Ensure we pass the connection to our app function

Read more about the bracket pattern

backend/Api.hs

{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}

module Api where

import qualified Model as M (1)
import qualified Storage as S
import Data.Aeson
import Control.Monad.IO.Class (MonadIO, liftIO)
import Control.Monad.Trans.Either
import Servant
import Database.SQLite.Simple as Sql

instance ToJSON M.Artist
instance FromJSON M.Artist

type ArtistAPI = (2)
Get '[JSON] [M.Artist]
:<|> ReqBody '[JSON] M.Artist :> Post '[JSON] M.Artist
:<|> Capture "artistId" Int :> Get '[JSON] M.Artist
:<|> Capture "artistId" Int :> ReqBody '[JSON] M.Artist :> Put '[JSON] M.Artist
:<|> Capture "artistId" Int :> Delete '[] ()

-- '

artistsServer :: Sql.Connection -> Server ArtistAPI (3)
artistsServer conn =
getArtists :<|> postArtist :<|> getArtist :<|> updateArtist :<|> deleteArtist

where
getArtists = liftIO $ S.findArtists conn (4)
getArtist artistId = liftIOMaybeToEither err404 $ S.artistById conn artistId
postArtist artist = liftIO $ S.newArtist conn artist
updateArtist artistId artist = liftIO $ S.updateArtist conn artist artistId
deleteArtist artistId = liftIO $ S.deleteArtist conn artistId

liftIOMaybeToEither :: (MonadIO m) => a -> IO (Maybe b) -> EitherT a m b
liftIOMaybeToEither err x = do (5)
m <- liftIO x
case m of
Nothing -> left err
Just x -> right x

type API = "artists" :> ArtistAPI

api :: Proxy API
api = Proxy

1
The record definitions for our API lives in this module

2
We’ve extended the api type defintions from episode 1
to define the shape of get multiple, get single, post, put and delete.

3
Connection has been added as a parameter to our artist server

4
liftIO is a monad transformer. I’d love to be able to explain
how it works, but well…​ Anyways net result is that I don’t have to define EitherT ServantErr IO .. all over the place

5
liftIOMaybeToEither - what it says. Handy function to return a servant error (which again maps to a http error) if a function like getArtist doesn’t return
a result. Tx to ToJans for inspiration

put aka update artist should also return a 404 when a non existing artist id is provided.
Actually, error handling is pretty light throughout, but we’ll get back to that in a later episode !

/backend/Model.hs

{-# LANGUAGE DeriveGeneric #-}

module Model where

import GHC.Generics

data Artist = Artist (1)
{ artistId :: Maybe Int (2)
, artistName :: String (3)
} deriving (Eq, Show, Generic)

1
Moved record defintions to a separate module. Currently just Artist

2
Make id optional. This is a quick and dirty way to be able to use the same
record definiton for new artists as for updates and gets.

3
Names in records are not scoped withing the record so one solution is to manually
make sure names stay unique.

From what I gather record syntax is a bit clunky in Haskell (atleast when compared to Elm).
This stackoverflow post
didn’t bring any warm fuzzy feelings. If anyone has some better solutions which also plays
well with the handy servant and SQLite simple functions feel free to leave a comment below !

backend/Storage.hs

{-# LANGUAGE OverloadedStrings #-}
module Storage where

import qualified Model as M
import qualified Data.Text as Txt

import Database.SQLite.Simple as Sql
import Database.SQLite.Simple.Types as SqlTypes

instance Sql.FromRow M.Artist where (1)
fromRow = M.Artist <$> Sql.field <*> Sql.field

artistById :: Sql.Connection -> Int -> IO (Maybe M.Artist) (2)
artistById conn idParam =
findById conn "artist" idParam :: IO (Maybe M.Artist)

findArtists :: Sql.Connection -> IO [M.Artist]
findArtists conn =
Sql.query_ conn "select * from artist" :: IO [M.Artist]

newArtist :: Sql.Connection -> M.Artist -> IO M.Artist
newArtist conn artist = do
Sql.execute conn "insert into artist (name) values (?) " (Sql.Only $ M.artistName artist)
rawId <- lastInsertRowId conn
let updArtist = artist { M.artistId = Just (fromIntegral rawId) } (3)
return updArtist

-- Really we should check whether the artist exists here
updateArtist :: Sql.Connection -> M.Artist -> Int -> IO M.Artist
updateArtist conn artist idParam = do
Sql.executeNamed conn "update artist set name = :name where id = :id" params
return artist { M.artistId = Just idParam } (4)
where
params = [":id" := (idParam :: Int), ":name" := ((M.artistName artist) :: String)]

deleteArtist :: Sql.Connection -> Int -> IO ()
deleteArtist conn idParam =
Sql.execute conn "delete from artist where id = ?" (Sql.Only idParam)

findById :: (FromRow a) => Sql.Connection -> String -> Int -> IO (Maybe a)
findById conn table idParam = do
rows <- Sql.queryNamed conn (createFindByIdQuery table) [":id" := (idParam :: Int)]
let result = case (length rows) of
0 -> Nothing
_ -> Just $ head rows (5)

return result

createFindByIdQuery :: String -> SqlTypes.Query
createFindByIdQuery table =
SqlTypes.Query $ Txt.pack $ "SELECT * from " ++ table ++ " where id = :id" (6)

-- ... boostrap function left out, check the source repo for details

1
Define SQLite row converter to create artist records for rows with id and name

2
Finding an artist by Id may return empty results. Prematurely factored out a generic findById function that is used here

3
Add the id of the newly inserted artist row to the resulting artist. (The Maybe artistId starts to smell)

4
Yuck, this smells even worse. The decision to support an optional id on the Artist record doesn’t ring true

5
Using let allows us to "work inside" the IO monad. Otherwise the compiler complains along the lines of Couldn’t match expected type ‘[r1]’ with actual type ‘IO [r0]’

6
Whacking strings together is discouraged (helps avoid sql injection for one), but getting around it is possible with a little serimony

Backend summary

Well now we got persistence up and running with a good ole' relational database. That’s
not very exciting and I might return to change that in a future episode. The REST api is quite simple and lacking in validation and error handling, but it’s hopefully a decent start and foundation
for future changes.

After working with Clojure and Leiningen not to long ago, the server startup time feels blistering fast in comparison.
Getting halive to work made significant improvements to the development workflow.
When working with Haskell I get a constant reminder that I would benefit from learning more about the language
and fundemental concepts. The compiler messages still throws me off a lot of times, but the situation is gradually improving as I’m learning.
I guess I’m already spoilt with the error messages from Elm which feels a lot clearer and better at highlighting the root cause(s) of my mistakes.

I’m still fumbling to design a sensible structure for the custom data types. I have a feeling
several iterations will be needed as I add support for additional services.

Frontend

It’s a shame the hot reloading support in elm-reactor is broken at the time of writing, otherwise the development experience
would have been a lot better. Makereload browser is just a keystroak away in Light Table, but still.
Having the informative compiler error and warning messages inline in my Editor is really nice though.

Do better understand the elm-architecture I’ve tried to follow, you should really check out the
tutorial. It does a much better job at explaining the core
concepts than I do.

albums pages

frontend/Main.elm

module Main where

import ArtistListing
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Task exposing (..)
import Effects exposing (Effects, Never)
import StartApp

type alias Model = (1)
{ artistListing : ArtistListing.Model}

type Action = (2)
ShowHomePage
| ArtistListingAction ArtistListing.Action

init : (Model, Effects Action) (3)
init =
let
(artistListing, fx) = ArtistListing.init
in
( Model artistListing
, Effects.map ArtistListingAction fx (4)
)

update : Action -> Model -> (Model, Effects Action)
update action model =
case action of

ShowHomePage -> (5)
let
(artistListing, fx) = ArtistListing.init
in
( {model | artistListing = artistListing}
, Effects.map ArtistListingAction fx
)

ArtistListingAction sub -> (6)
let
(artistListing, fx) = ArtistListing.update sub model.artistListing
in
( {model | artistListing = artistListing}
, Effects.map ArtistListingAction fx
)

menu : Signal.Address Action -> Model -> Html
menu address model =
header [class "navbar navbar-default"] [
div [class "container"] [
div [class "navbar-header"] [
button [ class "btn-link navbar-brand", onClick address ShowHomePage ]
[text "Albums Crud"]
]
]
]

view : Signal.Address Action -> Model -> Html
view address model =
div [class "container-fluid"] [
menu address model (7)
, ArtistListing.view (Signal.forwardTo address ArtistListingAction) model.artistListing
]

-- ... app, main and port for tasks left out, no changes since previous episode

1
The main model composes the artistlisting page model

2
Actions for main, currently just holds the actions for ArtistListing + a convenience action to reset/show home page

3
The init function from ArtistListing returns it’s model and an effect (get artist from server task). We initialize the
main model with the artistlisting model

4
We map the effect from ArtistListing to an Main module effect which is then handled by the startapp "signal loop"

5
Quick and dirty way to trigger showing of the artist listing page (re-initialized)

6
All ArtistListing actions are tagged with ArtistListingAction, we delegate to the update function for ArtistListing
, update the main model accordingly and the map the returne effect

7
To get/create the view for ArtistListing we call it’s view function, but we need to ensure signals sent from ArtistListing makes it back to the main view mailbox address. Signal.forwardTo helps us create a forwarding address.

Read more about Mailboxes, Messages and Addresses

frontend/ArtistListing.elm

module ArtistListing (Model, Action (..), init, view, update) where

import ServerApi exposing (..) (1)
import ArtistDetail
-- ... other imports ommited

type Page = ArtistListingPage | ArtistDetailPage

type alias Model =
{ artists : List Artist
, artistDetail : ArtistDetail.Model
, page : Page}

type Action =
HandleArtistsRetrieved (Maybe (List Artist))
| SelectArtist (Int)
| DeleteArtist (Int)
| HandleArtistDeleted (Maybe Http.Response)
| ArtistDetailAction ArtistDetail.Action
| NewArtist

init : (Model, Effects Action)
init =
let
(artistDetail, fx) = ArtistDetail.init
in
( Model [] artistDetail ArtistListingPage
, getArtists HandleArtistsRetrieved (2)
)

update : Action -> Model -> (Model, Effects Action)
update action model =
case action of

HandleArtistsRetrieved xs -> (3)
( {model | artists = (Maybe.withDefault [] xs) }
, Effects.none
)

DeleteArtist id ->
(model, deleteArtist id HandleArtistDeleted)

HandleArtistDeleted res ->
(model, getArtists HandleArtistsRetrieved)

NewArtist -> (4)
update (ArtistDetailAction <| ArtistDetail.ShowArtist Nothing) model

SelectArtist id ->
update (ArtistDetailAction <| ArtistDetail.GetArtist id) model

ArtistDetailAction sub -> (5)
let
(detailModel, fx) = ArtistDetail.update sub model.artistDetail
in
( { model | artistDetail = detailModel
, page = ArtistDetailPage } (6)
, Effects.map ArtistDetailAction fx
)

-- ... artistView details ommitted for brevity

view : Signal.Address Action -> Model -> Html
view address model =
div [class "content"] [
case model.page of (7)

ArtistListingPage ->
artistsView address model

ArtistDetailPage ->
ArtistDetail.view (Signal.forwardTo address ArtistDetailAction) model.artistDetail

]

1
The ServerApi module exposes functions to interact with the backend server

2
getArtists HandleArtistsRetrieved calls the serverAPI with a action param, so that when the ajax/xhr callback finally makes in back into the elm signal loop, the update function is called with the action we want

3
Update the model with the list of artists retrieved (if any)

4
To show the artist detail page in "create" mode we create a ArtistDetailAction with the appropriate ArtistDetail.action

5
ArtistDetailAction sub actions are actions that are delegated to the actions of the ArtistDetail module.

6
Note that we change "page context" here so that the view function displays the appropriate page

7
Our naive page routing, just toggles display of pages by the page attribute of our model

We’ve implemented a very simplistic page routing here. In a later episode we will refactor to
something more managable for handling proper page routing.

frontend/ArtistDetail.elm
This page handles update/creation of a single Artist. I’ll leave it to you to check out
the details of the sample code on github.

frontend/ServerApi.elm

module ServerApi where

import Json.Decode as JsonD exposing ((:=))
import Json.Encode as JsonE
import Effects exposing (Effects)
import Http
import Task

type alias ArtistRequest a = (1)
{ a | name : String }

type alias Artist =
{ id : Int
, name : String
}

baseUrl : String
baseUrl = "http://localhost:8081"

getArtist : Int -> (Maybe Artist -> a) -> Effects.Effects a
getArtist id action = (2)
Http.get artistDecoder (baseUrl ++ "/artists/" ++ toString id)
|> Task.toMaybe
|> Task.map action (3)
|> Effects.task

getArtists : (Maybe (List Artist) -> a) -> Effects a
getArtists action =
Http.get artistsDecoder (baseUrl ++ "/artists")
|> Task.toMaybe
|> Task.map action
|> Effects.task

createArtist : ArtistRequest a -> (Maybe Artist -> b) -> Effects.Effects b
createArtist artist action = (4)
Http.send Http.defaultSettings
{ verb = "POST"
, url = baseUrl ++ "/artists"
, body = Http.string (encodeArtist artist) (5)
, headers = [("Content-Type", "application/json")]
}
|> Http.fromJson artistDecoder
|> Task.toMaybe
|> Task.map action
|> Effects.task

-- .. the remaining services and encoding|decoding left out for brevity

1
This type is an extensible record type. It allows our
artist related services to be a little bit more generic and still keep a level of type checking

2
GET a single artist from our backend api. (Actually it returns and effect that will executa a task which upon callback will eventually call the update function in our app with the given action)

3
We’ve relented on type safety for actions by allowing it to be a generic param, but we gain some flexibility
that allows our service to be usable in many different contexts

4
To take more control over http actions we use Http.send. It’s closer to the metal so it’s a little
bit more boilerplate.

5
Encode the artist (request) to a json string

To see the remaining services and details of decoding and encoding please consolt the sample code on github.

Frontend summary

We are beginning to see the resmblance of a Single Page Application. We have started to compose
views and pages using the Elm Architecture. The app supports basic CRUD oparations for an Artist entity.
Error handling is light, there is no validation and our routing solution is overly simplistic, but we’ll get
to that soonish !

Working with Elm has been an absolute pleasure. The compiler messages really do help. Doing refactoring (without tests I might add)
doesn’t feel anywhere near as scary as I’m used to from other languages.
I’m starting to understand more about the Elm Architecture, but I’m still getting a little confused about the details
of Signals, Tasks, Mailboxes, Effects etc. It’s coming to me gradually. The important thing is I can still be quite productive
even though I don’t understand all the details.

I have to say I’m not looking forward to my next refactoring in some messy imperative jquery page mutant at work.

Conclusion and next steps

I’m aware this blog post got way to long even though I tried to shave of some of the code from the
code listings. I’ll have to try to take on smaller/more targeted chunks in future episodes.

Anyways. I’m staring to feel I’m getting somewhere now. Both with Haskell and Elm. Learning Haskell is
by far the most challenging but getting my head around Functional Reactive Programming in Elm isn’t without challenges either.
My motivation is still strong and I’m learning a ton of stuff.

Candidate areas to address for the next episode are; routing, validation, error handling and obviously more useful features.
I’m thinking perhaps routing comes first, but we’ll see.

Posted by LambdaCat on Wed, 01/13/2016 - 16:30

Road to Elm - Table of Contents

Destructuring is a handy tool, available in many functional languages (also in Javascript ES6).

It's a more succinct syntax to extract single values from collections of various types.

Extracting values from objects or arrays and assigning them to local variables is one of

Posted by LambdaCat on Tue, 01/12/2016 - 18:37

Road to Elm - Table of Contents

If you haven't programmed in an ML-inspired language before, let and in are probably new to you.

In an imperative language you can get away with sprinkling your variables all over the place. Nothing is enforcing their placement in a particular place in

Posted by LambdaCat on Mon, 01/11/2016 - 18:52

Road to Elm - Table of Contents

If you haven't used FP languages much, you may see many little confusing things happening in Elm code.

For one, you might have found partially applied functions, which are functions that take n arguments but are called with a less than n number

Posted by LambdaCat on Mon, 01/11/2016 - 18:51

I've been using Elm a lot lately, so I'm going to write down a series of posts of findings, thoughts and observations, both small & large, on concepts and corners of Elm that I feel are easy to overlook, counterintuitive or generally assumed to be known from previous Functional Programming

Posted by Rundis on Fri, 01/01/2016 - 01:00

In an effort to making management of project dependencies in Elm projects a little easier, the Elm plugin
for Light Table the elm-light has a few neat features up it’s sleave.
Check out the demo below for a brief overview.

You can find the elm-light plugin here

Demo

ScreenCast demo

Other relevant demos:

Short implementation summary

I’m just going to give a very brief overview of a few key pieces for how the features are implemented here.
I might add a more detailed blog post if there is any interest for that in the future.

Package management

The package manager is just a thin wrapper around the elm-package executable.

(defn parse-json-file [json-file]
(when (files/exists? json-file)
(-> (->> (files/open-sync json-file)
:content
(.parse js/JSON))
(js->clj :keywordize-keys true))))

(defn remove-pkg [path pkg]
(let [pkg-file (files/join path "elm-package.json")]
(-> (u/parse-json-file pkg-file)
(update-in [:dependencies] (fn [deps]
(-> (into {}
(map (fn [[k v]]
[(u/nskw->name k) v]) deps))
(dissoc pkg))))
u/pretty-json
((partial files/save pkg-file)))))

To list, update and remove dependencies it parses (and updates) the project file for elm projects; elm-package.json. In addition
it parses the exact-dependencies.json file for all resolved dependencies.

Working with json in ClojureScript feels almost seamless to working with native ClojureScript datastructures

View rendering

To render the package listing the plugin uses quiescent and react

(q/defcomponent PackageTable [props]
(d/table
{:className "package-table"}
(d/thead
{}
(d/tr
{}
(d/th {} "Package")
(d/th {} "Range")
(d/th {} "Exact")
(d/th {} "")))
(apply d/tbody {}
(map #(PackageRow (assoc %
:on-remove (:on-remove props)
:on-browse (:on-browse props)))
(:packages props)))))

You can find a detailed blog post about some of the benefits of using react for view rendering in Light Table
in Implementing a Clojure ns-browser in Light Table with React

Dependency autocompletion

Whan adding dependencies there is a handy autocompleter. This uses a json resource from http://package.elm-lang.org/.

(defn fetch-all-packages
"Fetch all packages from package.elm-lang.org"
[callback]
(fetch/xhr (str "http://package.elm-lang.org/all-packages?date=" (.getTime (new js/Date)))
{}
(fn [data]
(let [pkgs (js->clj (.parse js/JSON data) :keywordize-keys true)]
(callback pkgs)))))

Dependency graph

To implement the dependency graph d3 and dagreD3 is used. Both of these ships node-modules. Using node-modules from
Light Table plugins is definetely not rocket science !

(def dagreD3 (js/require (files/join u/elm-plugin-dir "node_modules/dagre-d3")))
(def d3 (js/require (files/join u/elm-plugin-dir "node_modules/d3")))

defn create-graph [data] (1)
(let [g (.setGraph (new dagreD3.graphlib.Graph) #js {})]
(doseq [x (:nodes data)]
(.setNode g (dep-id x) (node-label x)))
(doseq [x (:edges data)]
(.setEdge g (:a x) (:b x) #js {:label (:label x)
:style (when (:transitive x)
"stroke-dasharray: 5, 5;")}))
g))

(behavior ::on-render (2)
:desc "Elm render dependencies"
:triggers #{:elm.graph.render}
:reaction (fn [this]
(let [svg (.select d3 "svg")
g (.select svg "g")
renderer (.render dagreD3)]
(renderer g (create-graph (:data @this)))
(init-zoom svg g)
(resize-graph this svg))))

1
The function to create the dependency graph. Helper functions omitted, but not much to it really

2
Light Table behavior that is responsible for rendering the graph

Credits

  • d3.js - Provides awesome graphing features
  • dagreD3 - Create Directed Acyclic Graphs in a breeze
Posted by Gizra on Wed, 12/30/2015 - 00:00

In August 2015 I challenged myself (and later the rest of the Gizra devs) to create a typical web-app with all the bells and whistles in Elm. It's called elm-hedley, and I'm super proud it is now featuring in Elm's front page.

This post is going to give a high level overview and point out some parts that are worth noting. However, before diving into the technical section, it is important to emphasize the virtues of simply doing.

If you would go back in the commits history you would see some nasty stuff that have been completely overhauled and polished. The only way of getting to that "improving" part is of course by starting! Only after that will one become smarter and recognize what needs improving, as well as be more experienced to know how to do it.

Continue reading…

Posted by Rundis on Mon, 12/28/2015 - 01:00

Join me on my journey into statically typed functional languages. I’ve been living a pretty happily
dynamic life so far. What’s the fuzz with all those types ? What do they give me in a real life
scenario (aka is it worth using for work gigs) ? I need to make an effort and try to figure
some of this out. This blog series is an attempt to document some of my experiences along the way through a practical example.

There will be:

  • A single page web application with crud features
  • Lots of types, refactoring and hopefully some testing
  • An evolving web-app github repo for your amusement or amazement

Just a little background on me

For quite some time I’ve been wanting to learn more about functional languages that are statically (and strongly) typed.
What benefits do they really provide in practice and what are the downsides ?
My background is a from quite a few years with Java, and the last 3-4 years I’ve been working
mostly with Groovy, JavaScript and Clojure/ClojureScript.
I’ve dabbled a little with Elm recently (minesweeper in Elm)
, and I’ve tried to take on Haskell a couple of times (without much success I might add).

I mostly do web apps at work, so I figured I need to try and make something at least remotely
similar to what I do in real life.

Let’s get started

This is the point where I’ve run into analysis paralysis so many a time before.
So I set out to create a crud app, but what shall I build. After some deliberation
I settled on making something related to Music. You know Albums, Artists, Tracks and such.
I have no idea what the end result will be, but to start off I’ll make a simple spike.

artists

The spike should

  • establish a base architecture
  • implement a simple feature: List artists

You will find the sample application code on github.
There will be a tag for each blog post in the series

Backend

I wanted to implement server component that would provide REST-services. There are quite
a few options available for Haskell that can help with that. After some research and trials
I ended up using Servant.

Some of the other options I looked at includes:

I just had to choose one, and Servant seemed like a nice fit for REST stuff and I managed to get it
working without to much hazzle.

Project set up

I’m using cabal, but you might also want to consider looking
at stack.

name: albums
version: 0.1.0.0
synopsis: Albums rest backend
license: MIT
license-file: LICENSE
author: rundis
maintainer: mrundberget@hotmail.com
category: Web
build-type: Simple
cabal-version: >=1.10

executable albums
main-is: Main.hs (1)
build-depends:
base >= 4.7 && < 5
, either
, aeson >= 0.8 (2)
, servant (3)
, servant-server
, wai
, warp
hs-source-dirs: src (4)
default-language: Haskell2010

1
The entry point for the application

2
Provides JSON support

3
The servant library that helps us create type safe rest services

4
The directory(ies) where the source code for our app resides

For the purposes of this spike all haskell code will reside in Main.hs. This will
surely not be the case as the app progresses.

If you wan’t to try out automatic reloading support, you may want to check out halive.
Unfortunately I couldn’t get it to work on my machine (OS/X Maverick), but it might work our for you though :-)

Main.hs

data Artist = Artist
{ artistId :: Int
, name :: String
} deriving (Eq, Show, Generic)

A simple type describing the shape of an Artist in our app.

instance ToJSON Artist (1)

type ArtistAPI = (2)
Get '[JSON] [Artist] (3)
:<|> Capture "artistId" Int :> Get '[JSON] Artist (4)

artistsServer :: Server ArtistAPI
artistsServer = getArtists :<|> artistOperations (5)

where getArtists :: EitherT ServantErr IO [Artist]
getArtists = return artists (6)

artistOperations artistId =
viewArtist

where viewArtist :: EitherT ServantErr IO Artist
viewArtist = artistById artistId (7)

1
ToJSON is a type class. This line
basically is all we need to set up for json encoding an instance of our Artist type.

2
We describe our REST api using a type

3
Get on this api returns a list of Artists

4
Definition of how to get a single Artist by it’s id

5
The server type is the part where we descibe how we actually serve the api

6
The handler for listing artists. Currently it just returns a static list

7
The handler for retrieving a given artist by its id

:<> is a combinator that ships with Servant. It allows us to combine the various parts
of our API into a single type.

artistById :: Int -> EitherT ServantErr IO Artist
artistById idParam =
case a of
Nothing -> left (err404 {errBody = "No artist with given id exists"}) (1)
Just b -> return b (2)
where
a = find ((== idParam) . artistId) artists (3)

1
If the find (by id) in 3 returns Nothing (see Maybe monad).
We return a 404 error with a custom body

2
Upon success return the given artist instance

3
Find a given artist by id from our List of artists

EitherT - An either monad. Check out the description from the servant tutorial on EitherT

Wrapping it all up

type API = "artists" :> ArtistAPI (1)

api :: Proxy API
api = Proxy (2)

app :: Application
app = serve api artistsServer (3)

main :: IO ()
main = run 8081 app (4)

1
A generic type for our api. It let’s us combine multiple types, but the
main reason it’s factored out for now is to avoid repetion of the root path for our
api artists

2
TBH I haven’t grokked why this is needed, but it’s probably to do with some type magic ?

3
An "abstract" web application. serve gives us a WAI web application.
I guess WAI is like a common API for Haskell Web applicaitons.

4
The main entry point for our application. It starts our web application on port 8081
(and uses warp behind the scene to do so.)

To get the backend up and running, check out the readme for the sample application

Backend experiences

Following the Servant tutorial it was quite
easy to get a simple translated example to work. However I did start to struggle once I started
to venture off from the tutorial. Some of it is obviously due to my nearly non-existing haskell knowledge.
But I think what tripped me up most was the EitherT monad. Heck I still don’t really know what
a monad is. The error messages I got along the way didn’t help me much, but I guess gradually
they’ll make more and more sense, once my haskell foo improves.

Frontend

So Elm is pretty cool. The syntax isn’t too far off from Haskell. I’ve already started
looking at Elm so it makes sense continuing with Elm to hopefully gain deeper knowledge of its
strenghts and weaknesses.

For a really pleasurable experience when developing elm I would suggest choosing an
editor with linting support. As a shameless plug, one suggestion would be to use Light Table
with my elm-light plugin. (Emacs, Vim, Sublime, Visual Code are other good options)

Project setup

{
"version": "1.0.0",
"summary": "The frontend for the Albums CRUD sample app",
"repository": "https://github.com/rundis/albums.git",
"license": "MIT",
"source-directories": [
"." (1)
],
"exposed-modules": [],
"dependencies": { (2)
"elm-lang/core": "3.0.0 <= v < 4.0.0",
"evancz/elm-effects": "2.0.1 <= v < 3.0.0",
"evancz/elm-html": "4.0.2 <= v < 5.0.0",
"evancz/elm-http": "3.0.0 <= v < 4.0.0",
"evancz/start-app": "2.0.2 <= v < 3.0.0"
},
"elm-version": "0.16.0 <= v < 0.17.0"
}

1
For simplicity source files currently resides in the root folder of the project.
This will change once the application grows

2
Initial set of dependencies used

Album.elm

Before you start you may want to check out start-app.
The frontend code is based on this.

type alias Artist = (1)
{ id : Int
, name : String
}

type alias Model = (2)
{ artists : List Artist}

type Action = ArtistRetrieved (Maybe (List Artist)) (3)

1
Front end representation of Artist. You’ll notice it’s strikingly similar
to it’s Haskell counterpart on the server side

2
Type for keeping track of our model. Currently it will only contain
a list of artists, but there is more to come later

3
"Tagged type" that describes the actions supported in the frontend app.

init : (Model, Effects Action)
init = (1)
( Model []
, getArtists
)

update : Action -> Model -> (Model, Effects Action)
update action model = (2)
case action of
ArtistRetrieved xs ->
( {model | artists = (Maybe.withDefault [] xs) }
, Effects.none
)

getArtists : Effects.Effects Action
getArtists = (3)
Http.get artists "http://localhost:8081/artists"
|> Task.toMaybe
|> Task.map ArtistRetrieved
|> Effects.task

artist : Json.Decoder Artist
artist = (4)
Json.object2 Artist
("artistId" := Json.int)
("name" := Json.string)

artists : Json.Decoder (List Artist)
artists = (5)
Json.list artist

1
Initializer function called by start-app when staring the application
it returns an empty model and an effect getArtists. Meaning getArtists will be
invoked once the page is loaded

2
The update function handles actions in our app. Currently it only supports
one action, and that is the a callback once getArtists have returned. It updates
the model with the retrieved artists and returns the updated model

3
Our ajax call ! We invoke the our rest endpoint using the elm http library. The first
argument to Http.get, artists, tells elm how to decode the result.
A lot is going on here, but the end result is that it does an xhr request decodes the result (if success)
using the given decoder and eventually invoke the update function with our list of artists (wrapped in a Maybe).

4
A decoder for decoding the json representation of an artist from the server to and Artist type instance

5
The response from our rest endpoint is a list of artists, so we use the JSON.list function
telling it to use our artist decoder for each item in the list

artistRow : Artist -> Html
artistRow artist = (1)
tr [] [
td [] [text (toString artist.id)]
,td [] [text artist.name]
]

view : Signal.Address Action -> Model -> Html
view address model = (2)
div [class "container-fluid"] [
h1 [] [text "Artists" ]
, table [class "table table-striped"] [
thead [] [
tr [] [
th [] [text "Id"]
,th [] [text "Name"]
]
]
, tbody [] (List.map artistRow model.artists)
]
]

1
Function to generate the view for a single artist row

2
Our main view function for presenting a list of artists

We are not rendering dom nodes here, it’s just a representation of what we want
to render. The actual rendering uses Virual DOM.

Wrapping up the frontend

app : StartApp.App Model
app = (1)
StartApp.start
{ init = init
, update = update
, view = view
, inputs = []
}

main : Signal Html
main = (2)
app.html

port tasks : Signal (Task.Task Never ())
port tasks = (3)
app.tasks

1
Using startapp to wire up our core functions (init, update and view)

2
The entry point function for our frontend app

3
When communicating with the outside world elm uses ports.
This is used for by our rest invocation. It does so using tasks which
is the elm way to describe asynchronous operations.

Frontend experiences

Elm ports, tasks and effects are concepts that are yet to dawn completely on me. I protect my brain
temporarily by giving them overy simplistic explanations.
I wasn’t sure how to do the JSON decoding stuff, but fired up an elm-repl in Light Table and just experiemented a little until
I had something workable.
I used the linter feature of my Light Table plugin quite heavily, and the error messages from elm proved yet again
to be very helpful.

Conclusion and next steps

I pretty sure I could have knocked this up with Clojure/ClojureScript, groovy/grails or plan old JavaScript
in a fraction of the time I’ve used. But that’s not really a fair or relevant comparison.
Learning completely new languages and new libraries takes time.
I think I’ve learned quite a bit already and I’m very pleased to have made it this far !

Elm was easier to get into than Haskell and the Elm compiler felt a lot more helpful to me than
ghc (haskell compiler). I had a head start on Elm, but I do remember getting started with Elm felt
a lot smoother than jumping into Haskell. I’m still very much looking forward to improving my haskell skills
and I’m sure that will proove very valuable eventually.

So what’s up next? Not sure, but i think adding persistence and the facility to add/update
artists might be next up. I will keep you posted !

Posted by codecentric on Fri, 12/18/2015 - 18:39

Nearly all modules you’ll write in Elm need to import other modules to do their work; also, all our examples so far had some import statements. In this episode, we take a closer look at the import statement and at the different ways to import modules.

About This Series
This is the eighth post in a series of short and sweet blog posts about Elm. The stated goal of this series is to take you from “completely clueless about Elm” to “chief Elm guru”, step by step. If you have missed the previous episodes, you might want to check out the table of contents.
Qualified Imports
Let’s look at a basic example that just renders some static HTML:
import Html
import Html.Attributes

main : Html.Html
main =
Html.div []
[ Html.p [] [ Html.text "This is the first paragraph" ]
, Html.p [] [ Html.text "This is another paragraph" ]
, Html.hr [] []
, Html.ul []
[ Html.li [] [ Html.text "some" ]
, Html.li [] [ Html.text "bullet" ]
, Html.li [] [ Html.text "points" ]
]
, Html.p []
[ Html.text "This is the "
, Html.span
[ Html.Attributes.style [("font-weight", "bold")] ]
[ Html.text "closing"
]
, Html.text " paragraph."
]
]
This would render the following HTML:
<div>
<p>This is the first paragraph</p>
<p>This is another paragraph</p>
<hr>
<ul>
<li>some</li>
<li>bullet</li>
<li>points</li>
</ul>
<p>
This is the <span style="font-weight: bold;">closing</span> paragraph.
</p>
</div>
As always, go ahead and try stuff out for yourself, for example by copying this into a file named Imports.elm and check the result with elm-reactor.
This piece of Elm imports two modules, Html and Html.Attributes:

import Html
import Html.Attributes

An import statement basically tells the Elm compiler to load these two modules and to use stuff from them whenever it encounters anything that is prefixed with Html. (or Html.Attributes., respectively). Thus, we know that the functions Html.text or Html.Attributes.style that we are using in the example code come from said modules.
By the way, where do the imported modules come from? That depends. You can import modules from third party packages that have been installed via elm-package install. You can also import your own modules from your current project’s source folder (there will be a separate blog post on how to structure your code base with modules later).
In this example, we are importing modules from the package evancz/elm-html so you would need to install this via elm-package install --yes evancz/elm-html to follow along. If you already did the examples in episode 3 or episode 4 you can just create a new file (say, Imports.elm) in the same elm-playground directory and you are good to go. We already installed the elm-html package there.
Coming back to the example code, let’s be honest here: This code looks really bloated with all the redundant Html.qualifiers. This is where the exposing keyword comes in.
Open Imports aka Unqualified Imports
The following code example makes use of open imports by using import exposing, so that the imported identifiers can be used without prefix.

import Html exposing (Html, div, hr, li, p, span, text, ul)
import Html.Attributes exposing (style)

main : Html
main =
div []
[ p [] [ text "This is the first paragraph" ]
, p [] [ text "This is another paragraph" ]
, hr [] []
, ul []
[ li [] [ text "some" ]
, li [] [ text "bullet" ]
, li [] [ text "points" ]
]
, p []
[ text "This is the "
, span
[ style [("font-weight", "bold")] ]
[ text "closing"
]
, text " paragraph."
]
]

The first difference I would like to draw your attention to is in the import statement section:

import Html
import Html.Attributes

versus

import Html exposing (Html, div, hr, li, p, span, text, ul)
import Html.Attributes exposing (style)

By appending exposing to the import statement we can specify a list of identifiers that can be used unqualified (that is, without the module name as a prefix) in our module. That’s the reason why we can drop all the Html. prefixes in the main function. Html.text becomes just text, Html.p becomes p, and so on.
Another detail is that this does not only apply to functions but to all identifiers that a modules exports. In particular, it also applies to types. The type annotation in the first example had to be written as

main : Html.Html

This is because the name of the module that we import is Html and the name of the type that this module exports is also Html. Thus, the full qualified name of that type is Html.Html.
In the second example we added the name of the type to the list of identifiers to be exposed for unqualified usage – if you look close enough, you can spot the Html in the exposing clause for the Html import. With that, the type annotation in the second example can be written as

main : Html

Expose Everything
The second example already looks a bit cleaner. However, as soon as you start to use more and more HTML tags (or, functions from the Html module, that is) you always need to add them to the exposing part of the import. This can be a bit annoying. Elm has a special import syntax to avoid this.

import Html exposing (..)
import Html.Attributes exposing (..)

-- main function is the same as in the second example

With import Html exposing (..) we tell the Elm compiler to expose every identifier the Html module has to offer and we can use them all in their unqualified form.
Import Aliases
Another feature of the import statement is that you can alias the imported module.
Say, you would not want to import unqualified from Html.Attributes, for whatever reason. You would have to prefix the styles function call with Html.Attributes again, as in our first example. Html.Attributes.styles is pretty long though. What you can do is define an alias for that:

import Html.Attributes as Attr
Html.Attributes by prefixing them with Attr, like this:

Attr.style [("font-weight", "bold")]

You can also combine aliases and exposing. This might make sense if you only expose a few of the imported identifiers but still want a shorthand notation for the qualified usages.

import Html as H exposing (Html)

main : Html
main =
H.div [] [ H.text "whatever" ]

Here, we only expose the type Html for unqualified usage (thus, we can write the type annotation as main : Html instead of main : Html.Html) but alias the module name Html as H and use this alias to refer to the functions from Html. (Note: I do not recommend this approach, see below for some recommended best practices regarding imports.)
Default Imports
A small number of modules are imported into every module by default, even if you do not have explicit import statements for them. Here is the set of default imports (for Elm 0.16):

import Basics exposing (..)
import Debug
import List exposing ( List, (::) )
import Maybe exposing ( Maybe( Just, Nothing ) )
import Result exposing ( Result( Ok, Err ) )
import Signal exposing ( Signal )

This means that, for example, you can use every function from the Basics module, without prefixing them.
There are two things that might need a little explaining with these import statements.
First, the import statement for List exposes ( List, (::) ): The module List has a type named List that gets exposed. This is pretty straight forward and we have already seen this with the Html module. But what is this (::) about that also gets exposed? Function names in Elm usually use alphanumeric characters, but you can also use identifiers that only use non-alphanumeric characters (:, |, <, $, ...), you just need to wrap those names in parantheses in the function definition and when importing them. As you might recall from our last episode, :: is the append operator for lists. It is actually not something special build into the Elm compiler but just a regular function definition on the List module. We can use the function (::) everywhere because it is imported and exposed by default. Also, you can always use functions like this without the parantheses as infix operators. That's the reason why you can write [1, 2] :: [3, 4] in Elm without importing anything explicitly. You can also define your own infix operators that way.
Second, the exposing clauses for the Maybe and Result imports use syntax we have not covered yet. The module Maybe exports a union type named Maybe. We did not talk about union types yet. For now, it suffices to say that a union type is just an enumeration of type values. Here is the definition of the Maybe type:

type Maybe a = Just a | Nothing

So a value of type Maybe can either be Nothing or Just a for some other type a.
The import statement import Maybe exposing ( Maybe( Just, Nothing ) ) makes the two individual values from the union type (Just and Nothing) available to our code.
Best Practices for Import Statements
Now that we have completed our short tour of import statements in Elm, it is time to talk about some recommendations regarding code style.
The following are my personal preferences, you are welcome to come up with your own.

  1. Use qualified imports as much as possible. That is, prefer import Array over import Array exposing (..). This makes your code a bit more verbose, but it is immediately obvious where an identifier comes from.
  2. Use exposing (..) only for a few selected modules. Actually, I tend to only use it for Html, Html.Attributes and Html.Events at all, nothing else.
  3. Expose types that have the same name as their module. That is, for a (fictional) module named LinkedList, that also exports a type LinkedList, use import LinkedList exposing (LinkedList). This way, you can use the type in type annotations like someFunction : LinkedList instead of writing someFunction : LinkedList.LinkedList.
  4. Do not use aliases (import Something as Sth) to shorten module names. In my opinion the savings in characters it is not worth the additional cognitive load, especially when modules are aliased differently all over your code base.
  5. Do use aliases for multi-segment module names and use the last segment as the alias. Example: import Some.Thing.MyModule as MyModule.

A Word About Writing HTML in Elm
This episode is about import statements but somehow we also briefly touched the topic of how to produce HTML in a readable fashion. The third example given above (using import Html exposing (..) is okay-ish, but probably not the best we can do.
If you are used to templating languages, you might not like how that looks in Elm. There is a very good discussion about that on the elm-discuss mailing list. Go read it if you are interested in patterns to do this in a nice way. In particular, this answer seems to get it quite right from my point of view.
Last but not least, the modules elm-html-shorthand and elm-bootstrap-html might come in handy for this.
Remarks About Pre-0.15 Syntax
Elm is still relatively young and the syntax has changed a few times with the latest versions. The syntax will probably stay much more stable with the 1.0 release. There are still a lot of examples out there using older syntax. With regard to imports, version 0.15 brought some important changes, introducing the exposing keyword.
You might stumble over examples using the old syntax without the exposing syntax, like this:

import Html (..)
import Html.Attributes (style)

For this, just insert exposing between the module name and the list of exposed identifiers.
With this we conclude the eighth episode of this blog post series on Elm. Stay tuned for the next episode. See you next time!
The post Elm Friday: Imports (Part VIII) appeared first on codecentric Blog.

Posted by LambdaCat on Tue, 12/15/2015 - 15:30

I recently decided to retrain myself as a terminal Emacs user (I'm nostalgic for the '80s and my old glorious green and black terminal :P)

So I switched all my Elm editing from Sublime Text (which works and is pretty nice) to Emacs (which also works and is pretty nice)