Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 混合其中一种,也许是单子_Haskell_Monads - Fatal编程技术网

Haskell 混合其中一种,也许是单子

Haskell 混合其中一种,也许是单子,haskell,monads,Haskell,Monads,我想我知道如何级联相同类型的单子。我想将两个单子组合在一起,以执行基于它们的操作: 我认为下面的代码继续了这个问题:假设我们有一个函数,验证字符串是否包含“Jo”,如果是这样的话,在它后面附加“Bob”,还有一个函数验证字符串长度是否大于8 hello函数将在第一个结果上应用第一个,然后应用第二个,并在成功的情况下向所有结果返回“hello”,或者在错误的情况下返回“Nothing”(我不知道这个“Nothing”是什么,顺便说一句,左或右) 我相信我需要的是Monad transformer,

我想我知道如何级联相同类型的单子。我想将两个单子组合在一起,以执行基于它们的操作:

我认为下面的代码继续了这个问题:假设我们有一个函数,验证字符串是否包含“Jo”,如果是这样的话,在它后面附加“Bob”,还有一个函数验证字符串长度是否大于8

hello函数将在第一个结果上应用第一个,然后应用第二个,并在成功的情况下向所有结果返回“hello”,或者在错误的情况下返回“Nothing”(我不知道这个“Nothing”是什么,顺便说一句,左或右)

我相信我需要的是Monad transformer,但我找不到一个简明的例子来帮助我开始

我认为这并不是什么理论上的问题,因为Haskell软件包可以与任何一个或者其他人一起使用

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 " ++)