Я пишу систему в стиле подсказки-ответа с кучей различных комбинаций Maybe a, IO a и MaybeT IO a, и есть много вещей, которые нужно учитывать. Некоторые действия ввода-вывода, для которых нет недопустимых входных данных (и, следовательно, не заключены в MaybeT), некоторые (и возвращают MaybeT IO a), некоторые не являются действиями ввода-вывода, но могут завершиться ошибкой, поэтому возвращают Maybe a, а некоторые это просто значения, и мне начинает казаться, что я должен запоминать чрезмерные комбинации <$>, Just, fmap, MaybeT, lift, =<<,
и return
только для того, чтобы все было в правильном типе. Есть ли более простой способ управлять этим или рассуждать о том, какие функции мне нужно использовать, чтобы получить мои значения там, где они мне нужны? Или мне просто нужно надеяться, что со временем я стану лучше? Вот мой пример:
getPiece :: Player -> Board -> MaybeT IO Piece
getPiece player@(Player pieces _ _ _) board = piece
where
promptString = displayToUserForPlayer player board ++ "\n" ++ (display player) ++ "\n" ++ "Enter piece number: "
input :: MaybeT IO String
input = lift $ prompt promptString
index :: MaybeT IO Int
index = MaybeT <$> return <$> ((fmap cvtFrom1indexedInt) . maybeRead) =<< input
piece :: MaybeT IO Piece
piece = MaybeT <$> return <$> maybeIndex pieces =<< index
getRotatedPiece :: Player -> Board -> MaybeT IO Piece
getRotatedPiece player@(Player pieces _ _ _) board = piece
where
promptString :: MaybeT IO String
promptString = (++) <$> displayListString <*> restOfString
input :: MaybeT IO String
input = MaybeT <$> (fmap Just) <$> prompt =<< promptString
index :: MaybeT IO Int
index = MaybeT <$> return <$> ((fmap cvtFrom1indexedInt) . maybeRead) =<< input
piece :: MaybeT IO Piece
piece = MaybeT <$> return <$> maybeIndex pieces =<< index
rotatedPieceList :: MaybeT IO [Piece]
rotatedPieceList = rotations <$> getPiece player board
displayListString :: MaybeT IO String
displayListString = displayNumberedList <$> rotatedPieceList
restOfString :: MaybeT IO String
restOfString = MaybeT <$> return <$> Just $ "\nEnter rotation number:"
Должен сказать, я разочарован отсутствием лаконичности, даже если бы я удалил подсказки типов, я, вероятно, мог бы написать более короткую функцию, чтобы делать то же самое на C# или python.
lift
и попробуйте написать весь свой монадический код без использования конструкторов (это решит вашу проблему многословия, а также упростит рефакторинг) - person jberryman   schedule 07.12.2012