Skip to content

Instantly share code, notes, and snippets.

@queertypes
Created August 31, 2015 05:06
Show Gist options
  • Select an option

  • Save queertypes/d81aad1e0a63fd337729 to your computer and use it in GitHub Desktop.

Select an option

Save queertypes/d81aad1e0a63fd337729 to your computer and use it in GitHub Desktop.
Fun with Factorials: a purescript-halogen example
module Main where
import Prelude
import Control.Monad.Aff (runAff)
import Control.Monad.Eff (Eff())
import Control.Monad.Eff.Exception (throwException)
-- *very* explicit imports for slightly easier reading in a gist
import Data.Maybe (Maybe(Just, Nothing), maybe)
import Data.Int (fromString)
import Data.Functor (($>))
import Halogen
import Halogen.Query.StateF (modify)
import Halogen.Util (appendToBody)
import qualified Halogen.HTML as H
import qualified Halogen.HTML.Properties as P
import qualified Halogen.HTML.Events as E
import qualified Halogen.HTML.Events.Forms as E
--------------------------------------------------------------------------------
-- Data Model --
--------------------------------------------------------------------------------
newtype State = State { out :: String
, inp :: String
}
initialState :: State
initialState = State {out: "", inp: ""}
data Input a
= CalculateFactorial a
| ChangeText String a
factorial :: Int -> Int
factorial val = go val 1
where go n acc
| n <= 0 = acc
| otherwise = go (n-1) (acc*n)
--------------------------------------------------------------------------------
-- Component Definition: View + Controller --
--------------------------------------------------------------------------------
ui :: forall g p. (Functor g) => Component State Input g p
ui = component render eval
where
-- serves as event registration as well
-- look for E.onSOMETHING (E.input INPUT_TYPE)
-- That emits an event for `eval` to handle
render :: Render State Input p
render (State s) =
H.div_ [ H.h1_ [ H.text "Fun with Factorials" ]
, H.label [ P.for "factorial-input" ] [ H.text "Factorial: "]
, H.input [ P.type_ "text"
, P.value s.inp
, P.id_ "factorial-input"
, E.onValueChange (E.input ChangeText)
]
, H.br_
, H.label [ P.for "factorial-output" ] [ H.text "Is: " ]
, H.input [ P.type_ "text"
, P.value s.out
, P.id_ "factorial-output"
]
, H.br_
, H.button [ E.onClick (E.input_ CalculateFactorial) ] [ H.text "Calculate" ]
]
-- how we modify state in response to each type of input
eval :: Eval Input State Input g
eval (ChangeText s n) = modify saveInput $> n
where saveInput (State st) = State {inp: s, out: st.out}
eval (CalculateFactorial n) = modify tryCalculate $> n
where tryCalculate (State st) =
let output = maybe "error, not an integer" (show <<< factorial)
in State {inp: st.inp, out: output (fromString st.inp)}
--------------------------------------------------------------------------------
-- Output to the DOM --
--------------------------------------------------------------------------------
main :: Eff (HalogenEffects ()) Unit
main = runAff throwException (const (pure unit)) $ do
app <- runUI ui initialState
appendToBody app.node
@queertypes
Copy link
Copy Markdown
Author

and the HTML file to render everything:

<!doctype html>
<html>
  <head>
    <title>Halogen Example - Fun with Factorials</title>
    <style>
      body {
        font-family: sans-serif;
        max-width: 800px;
        margin: auto;
      }
    </style>
  </head>
  <body>
    <script src="example.js"></script>
  </body>
</html>

@soupi
Copy link
Copy Markdown

soupi commented Sep 1, 2015

Thank you for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment