Monadic擅长Haskell。我无法解决这个问题

时间:2016-04-02 14:17:02

标签: haskell

我正在尝试编写从字符串中提取数字的函数,例如:

"321 43 123 213" -> [321, 43, 123, 3212]
"dsa" -> Error
"123 da" -> Error

我想使用readEither和monadic方式(我尝试理解monads)。我的尝试:

import Text.Read

unit :: Either String [Int]
unit = Right []

extractInt :: String -> Either String [Int]
extractInt s =  helper (words s) where
    helper (h:t) = (bind readEither h) . (helper t)
    helper [] = Right []

bind :: (String -> Either String Int) -> String -> (Either String [Int] -> Either String [Int])
bind f x z = bind' (f x) z where
    bind' (Left s) _ = Left s
    bind' (Right i) (Right l) =  Right (l ++ [i])
    bind' (Left s) _  = Left s
  1. 请帮我解决问题。
  2. 请说出我的解决方案。
  3. 请说明我如何正确地做到这一点。 ;)
  4. 错误:

        Couldn't match expected type `a0 -> Either String [Int]'
                    with actual type `Either a1 [t0]'
        In the return type of a call of `Right'
        Probable cause: `Right' is applied to too many arguments
        In the expression: Right [1]
        In an equation for `helper': helper [] = Right [1]
    Failed, modules loaded: none.
    

2 个答案:

答案 0 :(得分:2)

您可以使用mapM函数对单词进行单一映射:

RDD

如果任何一个readEither调用都返回Left,那么该函数也会这样做。那是你在找什么?

答案 1 :(得分:2)

如果你想">> ="你的助手功能应如下所示:

helper [] = Right []
helper (w:ws) = readEither w >>= \i -> fmap (i:) (helper ws)

说明:显然,对于一个空的单词列表,我们需要一个空的整数列表。对于非空列表,我们对第一个单词readEither执行Either String Int,这会给我们Right。绑定(>> =)会将生成的整数传递给右侧的函数,但前提是结果为Left如果是helper这是帮助程序的总体结果

现在,(>> =)右侧的函数将Either String [Int]应用于剩余的单词。如我们所知,这将导致Right。然后,它会预先设置将{1}}结果中第一个单词转换为列表所产生的整数(如果有的话)。但是,如果helper返回Left值,则fmap不会更改任何内容,因此这将是整体结果。

所以带有(>> =)的第二行大致扩展为以下代码:

case readEither w of
    Left err  -> Left err
    Right int -> case helper ws of
        Left err -> Left err
        Right ints -> Right (int:ints)