Dan*_*rro 6 haskell coding-style monad-transformers
在真实世界 中,引入了Haskell monad作为一种避免代码通过使用Maybemonad 从屏幕右侧移动的方法.然而,当case语句包括其他单子像发生了什么Either或者IO,例如?
我知道使用monad变换器可以避免使用梯子,但是它们不仅仅是因为风格问题而过度杀伤吗?是否有其他惯用和轻量级的方法来处理这个?
更新:这是一个例子:
stair s = do
s <- getLine
case stepMaybe s of
Nothing -> return ()
Just s1 -> case stepEither s1 of
Left _ -> return ()
Right s2 -> case stepList s2 of
[s3:_] -> case stepMaybe s3 of
Nothing -> return ()
Just s4 -> print s4
_ -> return ()
Run Code Online (Sandbox Code Playgroud)
Gab*_*lez 10
使用专为此目的而创建的errors库.它允许您统一各种失败的计算,以就共同的错误处理机制达成一致.
例如,假设您有两个计算,其中一个计算失败Maybe,另一个计算失败Either String:
safeHead :: [a] -> Maybe a
safeHead as = case as of
[] -> Nothing
a:_ -> Just a
safeDivide :: Double -> Double -> Either String Double
safeDivide x y = if y == 0 then Left "Divide by zero" else Right (x / y)
Run Code Online (Sandbox Code Playgroud)
我们可以通过两种方式使这两个函数在相同的错误处理机制上达成一致.第一种方法是通过抑制错误将Either函数转换为a .这就是函数的作用:MaybeStringhush
-- Provided by the `errors` package
hush :: Either e a -> Maybe a
example1 :: [Double] -> Maybe Double
example1 xs = do
x <- safeHead xs
hush (safeDivide 4 x)
Run Code Online (Sandbox Code Playgroud)
或者,如果失败,我们可以使用Maybe描述性String错误消息来注释计算.这就是note函数的作用:
-- Also provided by the `errors` package:
note :: e -> Maybe a -> Either e a
example2 :: [Double] -> Either String Double
example2 xs = do
x <- note "Empty list" (safeHead xs)
safeDivide 4 x
Run Code Online (Sandbox Code Playgroud)
所述errors包还包括用于转换函数MaybeT和EitherT,太.这使您可以统一所有错误处理机制,以使用您选择的目标monad.
使用您的stair示例,您可以通过让他们达成一致来简化此操作MaybeT:
stair = void $ runMaybeT $ do
s <- lift getLine
s4 <- hoistMaybe $ do
s1 <- stepMaybe s
s2 <- hush $ stepEither s1
s3 <- headMay $ stepList s2
stepMaybe s3
lift $ print s4
Run Code Online (Sandbox Code Playgroud)