Haskell 也许在单子里
我想学习如何正确使用Haskell 我仍然不完全理解如何将Maybe用作另一个monad中的monad。告诉我,我可以做一些很棒的事情,也许没有模式匹配,只是在每一步都没有。请帮助我了解如何 我正在写一个Yesod处理程序,但在这种情况下这并不重要。重要的是Handler是一个单子Haskell 也许在单子里,haskell,monads,maybe,Haskell,Monads,Maybe,我想学习如何正确使用Haskell 我仍然不完全理解如何将Maybe用作另一个monad中的monad。告诉我,我可以做一些很棒的事情,也许没有模式匹配,只是在每一步都没有。请帮助我了解如何 我正在写一个Yesod处理程序,但在这种情况下这并不重要。重要的是Handler是一个单子 ugly :: Maybe ByteString -> Maybe MyObj ugly Nothing = Nothing ugly (Just text) = (decode . fromStrict) t
ugly :: Maybe ByteString -> Maybe MyObj
ugly Nothing = Nothing
ugly (Just text) = (decode . fromStrict) text
getHelloWorldR :: Handler Html
getHelloWorldR = do
myObjText <- lookupSessionBS "myobj" :: Handler (Maybe ByteString) -- gets serialized MyObj from a session cookie, or Nothing
myObj <- return $ ugly myObjText :: Handler (Maybe MyObj)
丑陋::也许是ByteString->也许是MyObj
丑陋的没有=没有
丑陋(仅文本)=(decode.fromStrict)文本
getHelloWorldR::处理程序Html
getHelloWorldR=do
myObjText=
但它需要奇怪的函数类型并返回奇怪的类型。我就是做不到。我查看了MaybeT
,但这意味着我需要定义一个类似于示例中ught
的函数,该函数返回MaybeT处理程序MyObj
。看起来太复杂了
编辑:用返回ByteString的LookupSessionB替换lookupSession。因为基于类型签名
解码。编码utf8。fromString
是一个函数文本->可能是MyObj
,我们可以在这里使用(>>=)
或其翻转对应项:
sugger::Maybe Text->Maybe MyObj
丑陋=(=
可以重写为
getHelloWorldR = do
myObjText <- lookupSession "myobj" :: Handler (Maybe Text)
let myObj = ugly myObjText :: Maybe MyObj
...
ugly :: Maybe Text -> Maybe MyObj
ugly maytext = maytext >>= decode . encodeUtf8 . fromStrict
因此,
getHelloWorldR = do
myObjText <- lookupSession "myobj" :: Handler (Maybe Text)
let myObj :: Maybe MyObj
myObj = myObjTest >>= decode . encodeUtf8 . fromStrict
...
getHelloWorldR=do
myObjText>=解码.encodeUtf8.fromStrict
...
您甚至不需要单子-您可以使用fmap
重写ught
:
ught=fmap$decode.fromStrict
此时,您甚至可以将其内联到getHelloWorldR
:
getHelloWorldR::Handler Html
getHelloWorldR=do
myObjText感谢您解释每一步。我无法过渡到使用>=
中的=
,但它确实非常简单!但是丑陋
返回一个Maybe MyObj
,fmap对它做了什么?它的类型会变成Maybe Text->Maybe(Maybe MyObj)吗
?我还惊讶地看到返回
在do符号之外。我不明白。什么是返回
“wrap”在这种情况下?@BloodySue记住部分应用和currying!fmap fx
将f
应用于值'inside'x
,因此fmap f
返回一个函数,给定值x
,该函数返回fmap fx
。至于返回return
,通常它会“包装”一些东西以将其放入mona中dic上下文,但正如您所注意到的,我写它的方式没有意义-我犯了一个错误,现在我将删除它,以便所有内容都进行类型检查!@BloodySue我还应该提到,当您应用某个内容,然后返回时,使用fmap
几乎更简洁易懂比使用>=
,因为a>=(\x->return(fx))
等于fmap fx
@BloodySue你的类型是对的Maybe(Maybe MyObj)
。通过使用join::Monad m=>m(ma)->ma
可以将其转换为Maybe MyObj
。因此我们得到join.fmap(decode.fromStrict)
--根据定义,这与(>>=(decode.fromStrict))
==(\m->m>=(decode.fromStrict))
==fmap fromStrict m>==decode
=do{xa->ma
本身就是一个函数,就像join
——它不是特殊的do
语法的一部分。对于Maybe
,返回x=Just x
)。根据Monad定律,do{x只需定义丑陋的::ByteString->MyObj
;然后fmap丑陋的::可能是ByteString->可能是MyObj
。我不能,因为Aeson.decode返回可能是MyObj
“=
需要奇怪的函数类型并返回奇怪的类型”你需要一直关注它,直到那些对你来说不再陌生。也可以查看=>
Kleisli合成操作符。它更容易掌握Monad定律。“Monad公理:Kleisli合成形成一个类别”。
getHelloWorldR = do
myObjText <- lookupSession "myobj" :: Handler (Maybe Text)
let myObj = ugly myObjText :: Maybe MyObj
...
ugly :: Maybe Text -> Maybe MyObj
ugly Nothing = Nothing
ugly (Just text) = (decode . encodeUtf8 . fromStrict) text
ugly :: Maybe Text -> Maybe MyObj
ugly maytext = maytext >>= decode . encodeUtf8 . fromStrict
getHelloWorldR = do
myObjText <- lookupSession "myobj" :: Handler (Maybe Text)
let myObj :: Maybe MyObj
myObj = myObjTest >>= decode . encodeUtf8 . fromStrict
...