Haskell 最佳实践 : Early termination in Haskeline

标签 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)

正如您所看到的,它完成了提前终止的任务,但看起来仍然有点令人讨厌。我正在考虑尝试将 notNothing 和 getInputLine 转换为一行,例如:

mone <- notNothing =<< lift $ getInputLine "food> " -- does not type check

我认为看起来没那么糟糕。我认为这是非常清晰和简洁的(尽管它没有类型检查,所以我必须编写一个可以进行类型检查的版本)。

但是,这是我想出的最好的方法,我的最终问题是:您将如何改进此代码以使其更整洁且更易于阅读?我是否走在正确的道路上?

编辑:如果你的防护不是“a/= Nothing”,那么我刚刚发现的一个很好的辅助函数是:

myGuard s = guard (someConditionFunc s) >> s

因为这样你就可以写(如 luqui 建议):

mone <- myGuard =<< (lift $ getInputLine prompt)

这很酷。但如果您只匹配 Nothing,那么 TomMD 的答案会更好。

最佳答案

为什么不直接利用 Maybe monad 的 fail _ = Nothing 这一事实呢?

mthree <- lift $ getInputLine "dessert> "
notNothing mthree

变成了

Just mthree <- lift $ getInputLine "dessert> "

关于Haskell 最佳实践 : Early termination in Haskeline,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4771199/

相关文章:

monads - 为什么在编写新的 Monad Transformers 时使用样板

Haskell:GHCi 将 Ctrl-Y 视为 Ctrl-Z

haskell - 使用 "deriving"时模板 Haskell 错误

haskell - Haskell语法错误

haskell - Parsec 不解析换行符

haskell - 混合 Threepenny-Gui 和 StateT

使用 HTF 进行测试

Haskell GTK 和 Monad 变压器

haskell - 如何在 Haskeline 中在运行时更改 Tab 完成的内容?

haskell - 更新 haskeline 中输出的文本