Rob*_*oli 5 haskell monad-transformers haskeline
我正在使用Haskeline程序包,我想在执行任何操作之前从命令行连续获取三个字符串,并且我已经想出了对我来说似乎是一个简洁的解决方案.但我相信可能有更好的方法来做到这一点.我正在寻找使用Haskeline包时的最佳实践.请评估以下示例代码的优点:
import System.Console.Haskeline
import Control.Monad.Trans
import Control.Monad.Maybe
import Data.Maybe
import Control.Monad
main :: IO ()
main = runInputT defaultSettings (runMaybeT getStrings) >>= print
getStrings :: MaybeT (InputT IO) (String, String, String)
getStrings = do
mone <- lift $ getInputLine "food> "
notNothing mone
mtwo <- lift $ getInputLine "drink> "
notNothing mtwo
mthree <- lift $ getInputLine "dessert> "
notNothing mthree
return (fromJust mone, fromJust mtwo, fromJust mthree)
where
notNothing a = guard (a /= Nothing)
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它完成了提前终止的任务,但它仍然看起来有点令人讨厌.我正在考虑尝试将notNothing和getInputLine转换为单行,如:
mone <- notNothing =<< lift $ getInputLine "food> " -- does not type check
Run Code Online (Sandbox Code Playgroud)
我认为这看起来并不那么糟糕.我认为这是非常清晰和简洁的(虽然它没有键入检查所以我将不得不编写一个版本).
然而,这是我提出的最好的,我的问题最终是:你将如何改进这个代码,使其更整洁,更容易阅读?我是否走在正确的轨道上?
编辑:如果你的后卫不是'a/= Nothing',那么我刚刚发现的一个好帮手功能是:
myGuard s = guard (someConditionFunc s) >> s
Run Code Online (Sandbox Code Playgroud)
因为那时你可以写(如luqui建议):
mone <- myGuard =<< (lift $ getInputLine prompt)
Run Code Online (Sandbox Code Playgroud)
这很酷.但如果你只与Nothing匹配,那么TomMD的答案会更好.
为什么不利用fail _ = NothingMaybe monad 的事实?
mthree <- lift $ getInputLine "dessert> "
notNothing mthree
Run Code Online (Sandbox Code Playgroud)
变
Just mthree <- lift $ getInputLine "dessert> "
Run Code Online (Sandbox Code Playgroud)