Я использую пакет 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 лучше.