Haskell 混合其中一种,也许是单子
我想我知道如何级联相同类型的单子。我想将两个单子组合在一起,以执行基于它们的操作: 我认为下面的代码继续了这个问题:假设我们有一个函数,验证字符串是否包含“Jo”,如果是这样的话,在它后面附加“Bob”,还有一个函数验证字符串长度是否大于8 hello函数将在第一个结果上应用第一个,然后应用第二个,并在成功的情况下向所有结果返回“hello”,或者在错误的情况下返回“Nothing”(我不知道这个“Nothing”是什么,顺便说一句,左或右) 我相信我需要的是Monad transformer,但我找不到一个简明的例子来帮助我开始 我认为这并不是什么理论上的问题,因为Haskell软件包可以与任何一个或者其他人一起使用Haskell 混合其中一种,也许是单子,haskell,monads,Haskell,Monads,我想我知道如何级联相同类型的单子。我想将两个单子组合在一起,以执行基于它们的操作: 我认为下面的代码继续了这个问题:假设我们有一个函数,验证字符串是否包含“Jo”,如果是这样的话,在它后面附加“Bob”,还有一个函数验证字符串长度是否大于8 hello函数将在第一个结果上应用第一个,然后应用第二个,并在成功的情况下向所有结果返回“hello”,或者在错误的情况下返回“Nothing”(我不知道这个“Nothing”是什么,顺便说一句,左或右) 我相信我需要的是Monad transformer,
validateContainsJoAndAppendBob :: String -> Maybe String
validateContainsJoAndAppendBob l =
case isInfixOf "Jo" l of
False -> Nothing
True -> Just $ l ++ "Bob"
validateLengthFunction :: Foldable t => t a -> Either String (t a)
validateLengthFunction l =
case (length l > 8) of
False -> Left "to short"
True -> Right l
-- hello l = do
-- v <- validateContainsJoAndAppendBob l
-- r <- validateLengthFunction v
-- return $ "Hello " ++ r
validateContainsJoAndAppendBob::String->Maybe String
validateContainsJoAndAppendBob l=
“Jo”l的案例
False->Nothing
正确->仅$l++“Bob”
ValidateLength函数::可折叠t=>TA->任一字符串(TA)
ValidateLength函数=
外壳(长度l>8)为
False->左“至短”
对->右l
--你好,l=do
--v使用函数将可能
转换为任一
note :: Maybe a -> e -> Either e a
note Nothing e = Left e
note (Just a) _ = Right a
hello l = do
v <- validateContainsJoAndAppendBob l `note` "Does not contain \"Jo\""
r <- validateLengthFunction v
return $ "Hello " ++ r
note::可能是a->e->e或者是a
注:无e=左e
注(仅a)\右a
你好,l=do
v除了李耀霞给出的实际答案,还有其他选择。这里有两个
也许是同构
可能a
与任一()a
同构,这意味着两者之间存在无损转换:
eitherFromMaybe :: Maybe a -> Either () a
eitherFromMaybe (Just x) = Right x
eitherFromMaybe Nothing = Left ()
maybeFromEither :: Either () a -> Maybe a
maybeFromEither (Right x) = Just x
maybeFromEither (Left ()) = Nothing
您可以使用其中一个来转换为另一个。由于validateLength函数
在失败时返回错误文本,因此将其返回值转换为可能字符串
值将是一种有损的转换,因此最好使用它们from可能
但问题是,这只会给您一个eather()字符串
值,您需要一个eather字符串
。您可以通过利用或作为Bifunctor
实例来解决此问题。首先,
import Data.Bifunctor
然后您可以将hello
编写为:
hello :: String -> Either String String
hello l = do
v <-
first (const "Doesn't contain 'Jo'.") $
eitherFromMaybe $
validateContainsJoAndAppendBob l
r <- validateLengthFunction v
return $ "Hello " ++ r
我更喜欢这个替代方案,但出于完整性考虑:
单子变压器
另一个选择是使用Monad变压器。您可以将可能
包装在EitherT
中,或者反过来将或者
包装在MaybeT
中。下面的示例执行后者
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Maybe (MaybeT(..))
helloT :: String -> MaybeT (Either String) String
helloT l = do
v <- MaybeT $ return $ validateContainsJoAndAppendBob l
r <- lift $ validateLengthFunction v
return $ "Hello " ++ r
如果要剥下MaybeT
包装,可以使用runMaybeT
:
*Q49816908> runMaybeT $ helloT "Cool Job, "
Right (Just "Hello Cool Job, Bob")
在大多数情况下,我可能会选择第一个选项…您想要的是(从分类意义上)从可能
到任意字符串
的自然转换,可能
函数可以提供
maybeToEither :: e -> Maybe a -> Either e a
maybeToEither e = maybe (Left e) Right
hello l = do
v <- maybeToEither "No Jo" (validateContainsJoAndAppendBob l)
r <- validateLengthFunction v
return $ "Hello " ++ r
您还可以使用=>
和return
将整个过程转换为一个巨大的无点定义
hello = maybeToEither "No Jo" . validateContainsJoAndAppendBob
>=> validateLengthFunction
>=> return . ("Hello " ++)
这是一个单子,不是一个游牧民族…编辑,谢谢,我将发明关于单子的游牧民族故事:-)我喜欢你的第一个选择。这真是一个一流的答案。谢谢。
maybeToEither :: e -> Maybe a -> Either e a
maybeToEither e = maybe (Left e) Right
hello l = do
v <- maybeToEither "No Jo" (validateContainsJoAndAppendBob l)
r <- validateLengthFunction v
return $ "Hello " ++ r
hello l = do
r <- validateLengthFunction <=< maybeToEither "No Jo" . validateContainsJoAndAppendBob $ l
return $ "Hello " ++ r
hello = maybeToEither "No Jo" . validateContainsJoAndAppendBob
>=> validateLengthFunction
>=> return . ("Hello " ++)