我正在编写一个提示 - 响应式系统,其中包含各种组合的Maybe a,IO a 和 MaybeT IO a。需要考虑许多问题。有些IO操作没有无效输入(因此没有包装在MaybeT中),有些则是(并返回MaybeT IO a);有些不是IO操作,但可能失败,所以返回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
,尝试编写所有单子代码,而不使用构造函数(这将解决您的冗长问题,并使重构更容易) 。 - jberryman