5

私はHaskelineパッケージを使用していて、何かをする前にコマンドラインから3つの文字列を続けて取得したいと思っています。そして、私にとってはきちんとした解決策と思われるものを思いつきました。しかし、私はそれを行うためのより良い方法があるかもしれないと確信しています。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を次のような1行に変換しようと考えています。

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の答えの方が優れています。

4

2 に答える 2

7

fail _ = Nothingという事実をMaybe モナドに活用してみませんか?

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

になる

Just mthree <- lift $ getInputLine "dessert> "
于 2011-01-22T23:14:31.263 に答える
4

ヘルパー関数はどうですか?

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

これはさまざまなトリックを使用して大幅に短縮できますが、明確にしたかったのです。getInputLineこれで、失敗する可能性があることを忘れることができMaybeTます。

于 2011-01-22T23:16:43.263 に答える