Я использую пакет 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)
Что довольно круто. Но если вы сравниваете только с Ничем, то ответ TomMD будет лучше.