The
Hyperbole effect is automatically available in both, and gives us direct access to the client connection. We can use it to get information about the
request, update the page directly, and more. Here is how you might use it to set the page title.
data Titler = Titler
deriving (Generic, ViewId)
instance HyperView Titler es where
data Action Titler
= SetTitle Text
deriving (Generic, ViewAction)
update (SetTitle msg) = do
pageTitle msg
pure "Check the title"
The following
HyperView uses a
Reader to get a message set at the application level. It also uses
Concurrent to delay the response by 500ms:
{-# LANGUAGE UndecidableInstances #-}
page :: (Hyperbole :> es, Concurrent :> es, Reader Text :> es) => Page es '[SlowReader]
page = do
pure $ hyper SlowReader $ messageView "..."
data SlowReader = SlowReader
deriving (Generic, ViewId)
instance (Concurrent :> es, Reader Text :> es) => HyperView SlowReader es where
data Action SlowReader
= GetMessage
deriving (Generic, ViewAction)
update GetMessage = do
threadDelay 500000
msg <- ask
pure $ messageView msg
Then make sure to add the effect when you run your application
app :: Application
app = do
liveApp quickStartDocument $ do
runConcurrent . runReader @Text "Secret!" $
runPage page
Databases and Custom Effects
We could run a database using the IOE effect, but it is better to describe the high-level operations available to the application as a custom effect:
data Todos :: Effect where
LoadAll :: Todos m [Todo]
Save :: Todo -> Todos m ()
Remove :: TodoId -> Todos m ()
Create :: Text -> Todos m TodoId
loadAll :: (Todos :> es) => Eff es [Todo]
loadAll = send LoadAll
Just like built-in effects, we add it to any
HyperView and
Page that needs it as a constraint.
{-# LANGUAGE UndecidableInstances #-}
simplePage :: (Todos :> es) => Page es '[AllTodos, TodoView]
simplePage = do
todos <- Todos.loadAll
pure $ do
hyper AllTodos $ todosView FilterAll todos
We run a custom effect in our Application just like any other. The
TodoMVC example implements the Todos
Effect using
Hyperbole sessions, but you could write a different runner that connects to a database instead.
main :: IO ()
main = do
run 3000 $ do
liveApp quickStartDocument (runTodosSession $ runPage simplePage)
Implementing a database runner as a custom
Effect is beyond the scope of this documentation, but see the following: