如何使 MonadError 与 ghcjs/reflex 一起工作
How to make MonadError work with ghcjs/reflex
我正在努力编译以下程序:
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.URLEncoded
import Reflex.Dom
url :: T.Text
url = T.pack "parm1=one&parm2=two"
main = do
mainWidget body
body :: MonadWidget t m => m ()
body = el (T.pack "div") $ do
-- let t = (T.pack "this program works if you replace the line below with this")
t <- fmap (T.pack . fromMaybe "" . Data.URLEncoded.lookup "parm2") (importString (T.unpack url))
text t
但是这个类似的版本适用于 vanilla ghc
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.URLEncoded
url :: T.Text
url = T.pack "parm1=one&parm2=two"
main = do
body
body = do
t <- fmap (T.pack . fromMaybe "" . Data.URLEncoded.lookup "parm2") (importString (T.unpack url))
T.putStrLn t
编译器说有些东西模棱两可,我不太确定如何实现它们。
The type variable ‘e0’ is ambiguous
Relevant bindings include body :: m () (bound at reflex.hs:14:1)
These potential instances exist:
instance [safe] Control.Monad.Error.Class.MonadError e (Either e)
-- Defined in ‘Control.Monad.Error.Class’
...plus 13 instances involving out-of-scope types
instance [safe] Control.Monad.Error.Class.MonadError
GHC.IO.Exception.IOException IO
-- Defined in ‘Control.Monad.Error.Class’
instance [safe] (Monad m, Control.Monad.Trans.Error.Error e) =>
Control.Monad.Error.Class.MonadError
e (Control.Monad.Trans.Error.ErrorT e m)
-- Defined in ‘Control.Monad.Error.Class’
仅供参考:我还没有完全掌握 Monads,很容易被这些错误吓到。求助!
在 ghc 版本中,importString
在 IO
monad do 语句的上下文中运行。 importString
能够 returning IO
monad 中的值,因此编译器很高兴
在 ghcjs 版本中,importString
在 m
monad do 语句的上下文中运行(m
在 body
的声明中指定)。 importString
无法 return m
monad 中的值,因此编译器会抱怨。
您可以通过使用 liftIO
将 IO
monad 值更改为 m
monad 值来解决此问题。这是您的代码,其中包含此更改以及我为帮助自己理解代码所做的一些其他更改。
import Data.Maybe
import qualified Data.Text as T
import Data.URLEncoded as DU
import Reflex.Dom
import Control.Monad.Trans as CMT
url :: T.Text
url = T.pack "parm1=one&parm2=two"
main = do
mainWidget body
body :: MonadWidget t m => m ()
body = el (T.pack "div") $ do
let istr = CMT.liftIO $ DU.importString (T.unpack url)
t <- fmap (T.pack . fromMaybe "" . DU.lookup "parm2") istr
text t
我正在努力编译以下程序:
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.URLEncoded
import Reflex.Dom
url :: T.Text
url = T.pack "parm1=one&parm2=two"
main = do
mainWidget body
body :: MonadWidget t m => m ()
body = el (T.pack "div") $ do
-- let t = (T.pack "this program works if you replace the line below with this")
t <- fmap (T.pack . fromMaybe "" . Data.URLEncoded.lookup "parm2") (importString (T.unpack url))
text t
但是这个类似的版本适用于 vanilla ghc
import Data.Maybe
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.URLEncoded
url :: T.Text
url = T.pack "parm1=one&parm2=two"
main = do
body
body = do
t <- fmap (T.pack . fromMaybe "" . Data.URLEncoded.lookup "parm2") (importString (T.unpack url))
T.putStrLn t
编译器说有些东西模棱两可,我不太确定如何实现它们。
The type variable ‘e0’ is ambiguous
Relevant bindings include body :: m () (bound at reflex.hs:14:1)
These potential instances exist:
instance [safe] Control.Monad.Error.Class.MonadError e (Either e)
-- Defined in ‘Control.Monad.Error.Class’
...plus 13 instances involving out-of-scope types
instance [safe] Control.Monad.Error.Class.MonadError
GHC.IO.Exception.IOException IO
-- Defined in ‘Control.Monad.Error.Class’
instance [safe] (Monad m, Control.Monad.Trans.Error.Error e) =>
Control.Monad.Error.Class.MonadError
e (Control.Monad.Trans.Error.ErrorT e m)
-- Defined in ‘Control.Monad.Error.Class’
仅供参考:我还没有完全掌握 Monads,很容易被这些错误吓到。求助!
在 ghc 版本中,importString
在 IO
monad do 语句的上下文中运行。 importString
能够 returning IO
monad 中的值,因此编译器很高兴
在 ghcjs 版本中,importString
在 m
monad do 语句的上下文中运行(m
在 body
的声明中指定)。 importString
无法 return m
monad 中的值,因此编译器会抱怨。
您可以通过使用 liftIO
将 IO
monad 值更改为 m
monad 值来解决此问题。这是您的代码,其中包含此更改以及我为帮助自己理解代码所做的一些其他更改。
import Data.Maybe
import qualified Data.Text as T
import Data.URLEncoded as DU
import Reflex.Dom
import Control.Monad.Trans as CMT
url :: T.Text
url = T.pack "parm1=one&parm2=two"
main = do
mainWidget body
body :: MonadWidget t m => m ()
body = el (T.pack "div") $ do
let istr = CMT.liftIO $ DU.importString (T.unpack url)
t <- fmap (T.pack . fromMaybe "" . DU.lookup "parm2") istr
text t