Created
August 31, 2015 05:06
-
-
Save queertypes/d81aad1e0a63fd337729 to your computer and use it in GitHub Desktop.
Fun with Factorials: a purescript-halogen example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
and the HTML file to render everything: