Warning: This is just a mind dump. It's not a coherent story and it's mostly for me to read back on my thought. I'm publishing it in the hope that other people can learn from my thought process.

To recap for the ones who aren't aware. Hom is a (hypothetical) library for writing (hopefully) blazingly fast clientside web applications using GHCJS. Its inspired by ReactJS which uses DOM diffing to calculate the optimal way to execute view changes. It basically turns your app into State -> Html . A great fit for the functional paradigm. Because I hate JS as much as you guys I decided to bring this lovely goodness to haskell. Luite and I made a start with the ghcjs-vdom library which is a thin wrapper around the js dom diffing algorithm. I was really enthousiastic but the project somehow ended up on my shel of "I'll start working on this project again when I feel like it"-projects.

Currently Hom is in the "showerthought" phase when every once in a while during a shower I come up with ways to improve my library.

This week I had to quickly create a dashboard for a TV at my university. I decided to use Elm. Development ended up being a joy and shipped the project after a day of elm-hacking.

The joy of working with elm-html was awesome. elm-html has similar goals to Hom though elm is a lot less powerful language than haskell.

I suggest reading up on Elm architecture tutorial before continuing.

One of the things that annoyed me during the project is that there is a lot of code duplication. Especially a lot of the same pattern matches to delegate actions down to sub-components etc.

Last night I was reading some lens stuff (one of those things I am trying to grock at this moment) and I started reading about prisms. "First class patterns" they're supposed to be. Well that sounds like something I could use right? I see that I keep doing the same kind of pattern matches for different scenarios. A 'pattern' seems to emerge (pun intended). Maybe I can abstract it with prisms? This was the shower thought.

So this morning I started type-hacking and I ended up with some awesome stuff.

I'm gonna assume for now that all elm's APIs are accessible in my hypothetical Hom library. All the following code is haskell.

We're gonna build an app that combines two apps into one. Namely it includes a Facebook and a Twitter widget.

The facebook and twitter widgets are defined as follow:

module Facebook where import Control.Lens import VirtualDom import Signal data Model = Model { _likes :: Int , _comments :: [String] } data Action = Like | Comment String deriving Show update :: Action -> Model -> Model update Like = ... upate (Comment s) = ... action :: Signal Action action = -- facebookAPISource + input events etc view :: Model -> Html view m = ... code that renders the facebook widget ...

And Twitter:

module Twitter where import VirtualDom import Signal data Model = Model { _status :: String } data Action = Tweet String | Favorite deriving Show update :: Action -> Model -> Model update (Tweet s) = ... update (Favorite) = ... action :: Signal Action action = -- twitter api and input events etc. view :: Model -> Html view m = -- code that renders the widget --

Now we want to combine these widgets. So our new model is going to be the union of those two widgets:

data Model = Model { _facebook :: Facebook.Model , _twitter :: Twitter.Model }

And the actions is going to be the union of the two widgets

data Action = FBAction Facebook.Action | TAction Twitter.Action | Close -- our own action for our own component

And our update function would be lame pattern matches. Every time we add a new subcomponent...

update :: Action -> Model -> Model update Close m = ... change the state so the app is closed ... update (FBAction a) m = m { _facebook = Facebook.update a (_facebook m) } update (TAction a) m = m { _twitter = Twitter.update a (_twitter m) }

Render the views...

view :: Model -> Html view m = div [] [ Facebook.view (m^.facebook) , Twitter.view (m^.twitter) ]

And run the app ...

app :: Signal Html app = Signal.foldp update initialState action

I don't know why but I wanted to hack this into something more nice with lenses and prisms.

Now we do:

makePrisms ''Action makeLenses ''Model

and we can start doing magic!

After reading the Prism documentation and stack overflow ( http://stackoverflow.com/questions/20774475/use-a-parameter-as-pattern-in-haskell) I found a way to easily extend your action handler.

say we have:

update' :: Action -> Model -> Model update' Close = .. state to close the app ..

and we want to add the facebook widget to that. We end up doing this:

update :: Action -> Model -> Model update = update' & outside _FBAction .~ over facebook . Facebook.update

If we want to add a twitter widget to that we can just add it to the chain:

update = update' & outside _FBAction .~ over facebook . Facebook.update & outside _TAction .~ over twitter . Twitter.update

We can extract this pattern into a utility function:

You should see it as: If we have a prism that given an action might give us a local action apply the local action to the global state by lensing into the global state to a part that is our local state and update that.

( I simplified the types a lot. Apparently this works for any Profunctor. not just (->) . Though I'm not sure what that means. Heck I don't even know what a Profunctor is. This lens library thing sure is complex.)

updateWith :: APrism' action localAction -> Setting' (->) model localModel -> (localAction -> localModel -> localModel) -> (action -> model -> model) -> (action -> model -> model) updateWith action lens update = outside action .~ over lens . update

So our code becomes:

withWidgets :: (Action -> Model -> Model) -> (Action -> Model -> Model) withWidgets = updateWith _FBAction facebook Facebook.update . updateWith _TAction twitter Twitter.update update = withWidgets update'

So now we can easily add as many widgets as we want using function composition! Nice! Because the local states of widgets don't overlap, the order in which we compose these updateWiths doesn't matter. widgets actions are commutative.

Okay so we got state updating covered. How do we delegate signals from the main component to subcomponents? Lets see how we used to do it in elm.

action_ :: Signal Action action = FBAction <$> Facebook.action <|> TAction <$> Twitter.action

Actually this is quite elegant. But I want to do it with prisms because heck why not.

With prisms we end up with the following code:

action :: Signal Action action = review _FBAction <$> Facebook.action <|> review _TAction <$> Twitter.action

We can extract a utility function:

mountAction :: Functor f => AReview t a -> f a -> f t mountAction r = (review r <$>) action = mountAction _FBAction Facebook.action <|> mountAction _TAction Twitter.action

This type is super general! I am going to dub it liftReview . It's simply review lifted into a functor.

Anyhow. Here my type-hacking endevaours stop. It was nice and I learned a lot about lenses. Haskell on the clientside web is awesome. I need to build this hypothetical library. It's gonna be sick.

peace.