Лучшие практики Haskell: раннее завершение работы в 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 ' s и getInputLine в одну строку вроде:

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

Что, на мой взгляд, не так уж плохо. Я думаю, что это довольно ясно и кратко (хотя в нем нет проверки типа, поэтому мне придется написать версию, которая делает).

Однако это лучшее, что я придумал, и, наконец, мой вопрос: как бы вы улучшить этот код, чтобы сделать его более аккуратным и читабельным? Я вообще на правильном пути?

Правка : Если ваша охрана - это нечто иное, чем «a / = Nothing», тогда я только что обнаружил прекрасную вспомогательную функцию:

myGuard s = guard (someConditionFunc s) >> s

Потому что тогда вы можете писать (как Луки предложил):

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

Что довольно круто. Но если вы сравниваете только с Nothing, то ответ TomMD лучше.

5
задан Community 23 May 2017 в 11:57
поделиться