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

发布于 2024-10-13 06:45:19 字数 1547 浏览 1 评论 0原文

我正在使用 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 的答案会更好。

I am using the Haskeline package and I want to get three strings in a row from the command line before I do anything and I have come up with what seems to be a neat solution to me. But I am sure that there might be a better way to do it. I am looking for best practices while using the Haskeline package. Please evaluate the merits of the following example code:

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)

As you can see it accomplishes the task of early termination but it looks a bit yucky still. I'm thinking of trying to convert the notNothing's and the getInputLine's into a single line like:

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

Which I think does not look that bad. I think that is pretty clear and concise (though it does not type check so I will have to write a version that does).

However, this is the best I have come up with and my question finally is: How would you go about improving this code to be neater and more readily readable? Am I even on the right track?

Edit: If your guard is something other than 'a /= Nothing' then a nice helper function that I just discovered is:

myGuard s = guard (someConditionFunc s) >> s

Because then you can write (as luqui suggested):

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

Which is pretty cool. But if you are matching against only Nothing then TomMD's answer is better.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

厌倦 2024-10-20 06:45:19

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

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

变成

Just mthree <- lift $ getInputLine "dessert> "

Why not just leverage the fact that fail _ = Nothing for the Maybe monad?

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

becomes

Just mthree <- lift $ getInputLine "dessert> "
稚然 2024-10-20 06:45:19

辅助功能怎么样?

inputLine :: String -> MaybeT (InputT IO) String
inputLine prompt = do
    m <- lift $ getInputLine prompt
    case m of
        Just x -> return x
        Nothing -> mzero

使用各种技巧可以大大缩短这个时间,但我想澄清一下。现在您可以忘记 getInputLine 可能会失败,MaybeT 会为您解决这个问题。

How about a helper function?

inputLine :: String -> MaybeT (InputT IO) String
inputLine prompt = do
    m <- lift $ getInputLine prompt
    case m of
        Just x -> return x
        Nothing -> mzero

This can be shortened considerably using various tricks, but I wanted to be clear. Now you can just forget that getInputLine can fail, MaybeT takes care of that for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文