BERĢI является только правом, но, возможно, вы найдете, что это легко понять, представлены следующим образом:
test :: String -> Either String [Int]
test str = traverse parseNumber (words str)
parseNumber :: String -> Either String Int
parseNumber str
| all isDigit str = Right (read str)
| otherwise = Left (str ++ " is not a number")
другая вещь, которую я рекомендовал бы это не писать хвостовой рекурсией аккумулятор петли, как iter
в вашем примере. Вместо этого просмотрите библиотечную документацию и попробуйте найти функции списка, которые делают то, что вы хотите. В этом случае, как правильно указал Берги, traverse
- это именно то, что вы хотите. Тем не менее, потребуется некоторое исследование, чтобы полностью освоить эту функцию. Но, учитывая, как Monad
экземпляр Either
и Traversable
экземпляр списков работы, traverse
в этом примере как это работает:
-- This is the same as `traverse` for lists and `Either`
traverseListWithEither :: (a -> Either err b) -> [a] -> Either err [b]
traverseListWithEither f [] = Right []
traverseListWithEither f (a:as) =
case f a of
Left err -> Left err
Right b -> mapEither (b:) (traverseListWithEither f as)
-- This is the same as the `fmap` function for `Either`
mapEither :: (a -> b) -> Either e a -> Either e b
mapEither f (Left e) = Left e
mapEither f (Right a) = Right (f a)
Почему вы aplicate два аргумента для readEither? Требуется только один аргумент (String) –
@HaskellFun: Спасибо. Я как-то ожидал, что он примет сообщение об ошибке и строку, подлежащую анализу. Исправлено сейчас, используя [удивительные бифунтеры] (http://hackage.haskell.org/package/base-4.8.2.0/docs/Data-Bifunctor.html#v:first) :-) – Bergi
Это не работает как мой soltuion. Он возвращает ошибку разбора без неправильной строки –