My intention is to alternate the colour of a div
between bright red and dark
red as a button gets pressed, starting with dark red.
I have this code:
{-# LANGUAGE
OverloadedStrings
#-}
module Main where
import Data.Map (Map)
import Reflex.Dom
main = mainWidget $ do
x <- greenButton
y <- toggle False x
let z = fmap style y
elDynAttr "div" z blank
style :: Bool -> Map String String
style b | b = "style" =: "height: 10ex; width: 10ex; background-color: #f00;"
| otherwise = "style" =: "height: 10ex; width: 10ex; background-color: #900;"
greenButton :: MonadWidget t m => m (Event t ())
greenButton = button "[ ]" -- Should be green but whatever.
It errors out thus:
• No instance for (Functor (Dynamic Spider))
arising from a use of ‘fmap’
• In the expression: fmap style y
In an equation for ‘z’: z = fmap style y
In the second argument of ‘($)’, namely
‘do { x <- greenButton;
y <- toggle False x;
let z = fmap style y;
elDynAttr "div" z blank }’
I certainly see an fmap
for Dynamic
in the quick reference,
though I am not sure the version of the reference and the version of the
reflex
package I compile against are consistent.
This is the stack.yaml
I use for building:
resolver: lts-7.19
compiler: ghcjs-0.2.1.9007019_ghc-8.0.1
compiler-check: match-exact
setup-info:
ghcjs:
source:
ghcjs-0.2.1.9007019_ghc-8.0.1:
url: http://ghcjs.tolysz.org/ghc-8.0-2017-02-05-lts-7.19-9007019.tar.gz
sha1: d2cfc25f9cda32a25a87d9af68891b2186ee52f9
extra-deps:
- reflex-dom-0.3
- ghcjs-dom-0.2.4.0
- ref-tf-0.4.0.1
- reflex-0.4.0.1
allow-newer: true
What am I doing wrong? And who the hell is this guy Spider?
The discussion below explains why Functor
for Dynamic
turned out to be a bad idea.
https://github.com/reflex-frp/reflex/pull/39
The problem with this instance is that it will evaluate
f
twice whenever the input dynamic changes: once to compute the newEvent
value, and once to compute the newBehavior
value. WithmapDyn
, there is only a single computation, the result of both is shared. This is also whymapDyn
is monadic.
So the code would look like this:
main = mainWidget $ do
x <- greenButton
y <- toggle False x
z <- mapDyn style y -- monadic mapDyn instead of fmap
elDynAttr "div" z blank
On the issue of documentation, Quickref.md
for version 0.4.0.1
is here and only references mapDyn
.
The Quickref.md
you linked to is the one for the future reflex-0.5
(the current develop
branch), which is reworking Dynamic
to have a Functor
instance. See their wiki:
Why doesn't Dynamic have Functor/Applicative/Monad instances
Reflex is scheduled to get these instances in version 0.5. As of this writing the implementation is mostly complete and is undergoing final polish and testing before release and is currently available on github in reflex's develop branch.