Skip to content

Instantly share code, notes, and snippets.

@andreabedini
Created February 20, 2019 05:09
Show Gist options
  • Select an option

  • Save andreabedini/14c95e1f639a4620eef6b4d0dac1b0a2 to your computer and use it in GitHub Desktop.

Select an option

Save andreabedini/14c95e1f639a4620eef6b4d0dac1b0a2 to your computer and use it in GitHub Desktop.
Experimenting with Reflex at the PerthFP meetup (18/02/2019)
with-compiler: ghc-8.4.4
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Aeson
import qualified Data.Text as T
import Language.Javascript.JSaddle.Warp
import Reflex.Dom.Core
import Reflex.Dom.Xhr
main = do
putStrLn "Running on http://localhost:3911, go check it out"
run 3911 $ mainWidget $ do
el "h1" (text "PerthFP is the best meetup")
counter
xhr
--
-- counter example (ah!)
--
data Cmd = Up | Down
counter :: forall t m. (MonadHold t m, MonadWidget t m) => m ()
counter = el "div" $ do
eUp <- button "up"
eDown <- button "down"
let eP = succ <$ eUp
eM = pred <$ eDown
counter <- foldDyn ($) 0 $ leftmost [eP, eM]
display counter
--
-- xhr example
--
newtype UserAgent = UserAgent T.Text
deriving Show
instance FromJSON UserAgent
where
parseJSON = withObject "UserAgent" $ \v -> UserAgent <$> v .: "user-agent"
xhr :: forall t m. (MonadHold t m, MonadWidget t m) => m ()
xhr = el "div" $ do
-- A button and its clicked event
-- eGetUserAgent :: Event t ()
eGetUserAgent <- button "GetUserAgent"
-- An event that carries the url to fetch, when the button is clicked
-- eUrl :: Event t T.Text
let eUrl = "https://httpbin.org/user-agent" <$ eGetUserAgent
-- Turns an Event t T.Text into an Event t (Maybe a) where a is the
-- type you want to decode from JSON
userAgentEvent <- getAndDecode eUrl
-- I want something to be displayed at all times, even before the
-- button is clicked for the first time. I can do this by providing an
-- intial value (Nothing) and turning the Event t (Maybe a) into a
-- Dynamic t (Maybe a).
heldUserAgent <- holdDyn Nothing userAgentEvent
-- Now I can display heldUserAgent which has a well-defined value at
-- all times, I can display that.
-- This ends up being too polymorphic since getAndDecode will decode
-- any type FromJSON a => a and display will display any Show a => a.
-- Nothing is telling the compiler what that a is supposed to be in my
-- program so I need to put a type annotation somewhere.
display (heldUserAgent :: Dynamic t (Maybe UserAgent))
-- Note: getting that type annotation right was not entirely trivial
-- because t has to bind to the top-level t in the type of xhr (i.e. it
-- is not just another variable casually named t). For this to work we
-- need to turn on ScopedTypeVariables and add the explicit forall in
-- the xhr type declaration.
-- GHC also suggested I'd turn on MonoLocalBinds but I have no idea
-- what it does.
cabal-version: >=1.10
name: tmp-reflex
version: 0.1.0.0
author: Andrea Bedini
maintainer: andrea@andreabedini.com
build-type: Simple
executable tmp-reflex
main-is: Main.hs
build-depends: base >=4.10 && <4.13
, aeson
, jsaddle-warp
, reflex
, reflex-dom
, text
default-language: Haskell2010
ghc-options: -threaded
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment