Невозможно отобразить через Dynamic: нет экземпляра для (Functor (Dynamic Spider))

Мое намерение состоит в том, чтобы изменить цвет div между ярко-красным и темно-красным при нажатии кнопки, начиная с темно-красного.

У меня есть этот код:

{-# 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.

Это ошибка таким образом:

• 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 }’

Я конечно вижу fmap за Dynamic в краткой справке, хотя я не уверен, что версия справки и версияreflex Пакет, который я собираю, соответствует.

Это stack.yaml Я использую для строительства:

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

Что я делаю неправильно? И кто, черт возьми, этот парень, Паук?

1 ответ

Решение

Обсуждение ниже объясняет, почему Functor за Dynamic оказалась плохой идеей.

https://github.com/reflex-frp/reflex/pull/39

Проблема с этим экземпляром в том, что он будет оценивать f дважды, когда изменяется входная динамика: один раз для вычисления нового Event значение и один раз для вычисления нового Behavior значение. С mapDyn, есть только одно вычисление, результат обоих является общим. Это также почему mapDyn монадический


Таким образом, код будет выглядеть так:

main = mainWidget $ do
    x <- greenButton
    y <- toggle False x
    z <- mapDyn style y      -- monadic mapDyn instead of fmap
    elDynAttr "div" z blank

По вопросу документации, Quickref.md для версии 0.4.0.1 здесь и только ссылки mapDyn,

Quickref.md Вы связаны с тем, на будущее reflex-0.5 (электрический ток develop филиал), который переделывает Dynamic иметь Functor пример. Смотрите их вики:

Почему в Dynamic нет экземпляров Functor/Applicative/Monad

Рефлекс планируется получить эти экземпляры в версии 0.5. На момент написания этой статьи реализация в основном завершена и проходит окончательную доработку и тестирование перед выпуском и в настоящее время доступна на github в ветке разработки reflex.

Другие вопросы по тегам