Haskell最佳实践:在Haskeline中提前终止

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的答案会更好.

Tho*_*son 7

为什么不利用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)