gpt4 book ai didi

haskell - 使用 Maybe a、IO a 和 MaybeT IO a

转载 作者:行者123 更新时间:2023-12-02 02:51:12 24 4
gpt4 key购买 nike

我正在编写一个提示 - 响应风格的系统,其中包含一系列 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 中做同样的事情

最佳答案

由于您仅提供了一个代码片段,因此我无法尝试对其进行重构。但是,这就是我要做的:大多数 monad 都有相应的类型类。这样做的原因正是您在这里需要的:当您使用 monad 转换器创建 monad 时,它将继承内部 monad 的操作(如果合适)。所以你可以忘记内部 monad,只在最后的 monad 中工作。

在你的情况下,你有 MaybeT IO .它是 MonadPlus 的实例和 MonadIO .所以你可以重构返回 Maybe something 的代码与将军一起工作 MonadPlus相反,只需替换 JustreturnNothingmzero .喜欢:

-- before
checkNumber :: Int -> Maybe Int
checkNumber x | x > 0 = Just x
| otherwise = Nothing x
-- after
checkNumber :: MonadPlus m => Int -> m Int
checkNumber x | x > 0 = return x
| otherwise = mzero
-- or just: checkNumber = mfilter (> 0) . return

它适用于任何 MonadPlus ,包括 MaybeMaybeT IO .

你可以重构返回 IO something 的代码与将军一起工作 MonadIO实例:
-- before
doSomeIO :: IO ()
doSomeIO = getLine >>= putStrLn
-- after
doSomeIO :: MonadIO m => m ()
doSomeIO = liftIO $ getLine >>= putStrLn

这样,您就可以忘记 <$>/ fmap/ liftM , Just , MaybeT等等。您只需使用 return , mzero在某些地方 liftIO .

这也将帮助您创建更通用的代码。如果您后来意识到需要向 monad 堆栈添加一些内容,则现有代码不会中断,只要新的 monad 堆栈实现相同的类型类。

关于haskell - 使用 Maybe a、IO a 和 MaybeT IO a,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13751430/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com