我对Haskell相当新,我想表达可能会或可能不会发生的IO动作的概念。
Network.URI提供了解析URI的功能
parseURI :: String -> Maybe URI
在我的主要功能中,我从用户那里获得输入
main :: IO ()
main = do
url <- getLine
getResource url
并使用parseURI函数
getResource :: String -> Maybe (IO ())
getResource url = parseURI url >>= doStuff
doStuff :: URI -> Maybe (IO ())
doStuff = undefined
正如您所看到的,我想使用>>=
来避免case of
级联,我会处理Maybes。
我已经设法通过将IO嵌入到Maybe中来实现。我想表达可能会或可能不会发生的IO操作的情况。我该怎么用?我肯定不是第一个遇到这个问题的人。我已经研究过MaybeT和MonadIO,但我不确定这是我需要的。
具体来说,如果我将doStuff移到MaybeT IO ()
,我仍然坚持使用parseURI url :: Maybe String
。如果我现在将其提升到MaybeT,我会MaybeT Maybe String
,但这与doStuff :: MaybeT IO ()
无法匹配
我希望看起来更好(如果可能的话)并了解什么是正确的方向以及使用哪些主流工具。
感谢您的时间和建议。
答案 0 :(得分:3)
首先关闭:可能发生或不发生IO ()
行为的类型可能只是IO ()
:您不关心结果,或者是否成功,您只是希望它在可能的情况下执行 。
如果你关心成功,那么有两种选择。
Maybe (IO ())
是动作的类型或不是动作,但是否是透明的“纯值”。即,如果您在顶层有Maybe (IO ())
值,则您可以确定某个操作是否可能发生而无需先实际执行任何IO
。但是这不是一个值的类型,你首先必须做一些IO来确定关键动作是否会发生,因为为了绑定任何IO,你必须在Just
分支中Maybe
!因此,如果成功取决于用户提供的字符串,那么这对您来说可能是正确的类型。IO (Maybe ())
是IO
操作的类型,可以执行确定要采取的操作所需的任何操作。该类型实际上等同于IO Bool
- IO
操作返回一些指示标记。您可以指定 Just ()
表示某些关键操作已经发生,而Nothing
表示它没有,但是没有办法真正从签名。 MaybeT IO ()
等同于后者,实际上可能是您应用程序的最佳类型。只是,你需要正确地进行变压器升降! lift
从变换器堆栈中的 down 开始执行操作,直到该堆栈的顶部。因此lift
!例如,您需要将IO
正常的getLine :: IO String
操作提升到MaybeT IO
堆栈中:
lift getLine :: MaybeT IO String
但是,如果您有一个纯Maybe
值,则需要“支持”它以获得MaybeT IO
。最简单的方法是直接使用MaybeT
构造函数。
getResource :: String -> MaybeT IO ()
getResource url = MaybeT (return $ parseURI url) >>= doStuff
doStuff :: URI -> MaybeT IO ()
doStuff = undefined