haskell - 如何避免 MaybeT 中的提升以及为什么最终验证无效?
问题描述
我们如何避免——如果这样做有意义的话..——使用lift
in MaybeT
?
wikibooks中的经典示例。
给定
isValid :: String -> Bool
isValid s = length s >= 8
&& any isAlpha s
&& any isNumber s
&& any isPunctuation s
我们有
getPassphrase :: MaybeT IO String
getPassphrase = do s <- lift getLine
guard (isValid s) -- Alternative provides guard.
return s
askPassphrase :: MaybeT IO ()
askPassphrase = do lift $ putStrLn "Insert your new passphrase:"
value <- getPassphrase
lift $ putStrLn "Storing in database..."
我试过的
我想我需要使用ask
and tell
,所以我将代码转换如下:
getPassphrase :: MaybeT (ReaderT String IO) String
getPassphrase = do
s <- ask
guard (isValid s) -- Alternative provides guard.
return s
askPassphrase :: MaybeT (ReaderT String IO) ()
askPassphrase = do
-- _ <- tell "Insert your new passphrase:"
value <- getPassphrase
-- _ <- tell "Storing in database..."
return ()
main :: IO (Maybe ())
main =
runReaderT (runMaybeT askPassphrase) "test123!"
该字符串"test123!"
产生Just()
while"test123"
返回Nothing
,因此 IMO它确实按预期工作,但我仍然必须包含 Writer。
如果我做
askPassphrase :: MaybeT (ReaderT String (WriterT String IO)) ()
askPassphrase = do
_ <- tell "Insert your new passphrase:"
let value = getPassphrase
_ <- tell "Storing in database..."
return ()
main :: IO ()
main =
execWriterT (runReaderT (runMaybeT askPassphrase) "test123!") >>= putStrLn
它编译并运行但出现问题,因为任何字符串都被认为是有效的,我的意思是我总是"Insert your new passphrase:Storing in database..."
在输出中看到。我错过了什么?
解决方案
我只需要使用:t
命令找到我的函数的正确类型,然后指定它们,它们是
getPassphrase :: MaybeT (ReaderT String (WriterT String IO)) [Char]
getPassphrase = do
和
askPassphrase :: MaybeT (ReaderT String (WriterT String IO)) ()
askPassphrase = do
并且lift
可以避免!(在问题的第二部分ask
已经没有了)lift
askPassphrase = do
tell "Insert your new passphrase:"
value <- getPassphrase
tell "Storing in database..."
在线版本在这里。
推荐阅读
- objective-c - 如何在 Mojave 中归档 NSSortDescriptor 数组
- c# - 如何从后面的代码绑定 ASP.NET Web Forms C# 应用程序的下拉列表中的“SelectedValue”?
- excel - 自动格式化单元格的不同颜色的部分
- javascript - 在单个通用更新模式中转换圆圈和文本(在 g 元素内)
- sql - 按 SQL 正确分组
- r - 计算随机数介于数据集中两个数字之间的概率
- firebase - Firebase auth().createUser - 发出请求时出错:超过 10000 毫秒的超时
- php - 磅符号编码 - 不适用于 iOS 的 Outlook
- javascript - 在 SelectDateWidget 中单独更改月、年和日期宽度
- reactjs - 使用 React 和 Pyramid(微服务架构)进行身份验证,如何存储“会话数据”?