- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写我的第一个Haskell应用程序,并且很难理解Monad变压器的用法。
示例代码:
-- Creates a new user in the system and encrypts their password
userSignup :: Connection -> User -> IO ()
userSignup conn user = do
-- Get the encrypted password for the user
encrypted <- encryptPassword $ password user. -- encryptPassword :: Text -> IO (Maybe Text)
-- Updates the password to the encrypted password
-- if encryption was successful
let newUser = encrypted >>= (\x -> Just user { password = x })
-- Inserts the user using helper function and gets the result
result <- insertUser (createUser conn) newUser
return result
where
insertUser :: (User -> IO ()) -> (Maybe User) -> IO ()
insertUser insertable inuser = case inuser of
Just u -> insertable u -- Insert if encryption was successful
Nothing -> putStrLn "Failed to create user" -- Printing to get IO () in failure case
insertUser
没有产生任何输出的情况下,如何避免像打印到控制台这样的操作(在
IO
辅助功能中完成)。更具体地说,如何为IO monad创建“零”值?
最佳答案
编辑:更新的答案以匹配您更新的问题。
需要明确的是,您的代码示例中实际上并未使用任何monad转换器。您只是将一个单子嵌套在另一个单子中。有关使用真实monad变压器MonadT
的示例,请参阅我对第二个问题的回答。
对于第一个问题,正如@David Young所说,可以使用return ()
:
showSuccess :: Bool -> IO ()
showSuccess success =
if success then putStrLn "I am great!"
else return () -- fail silently
IO a
返回
a
,则始终可以通过使用
return
函数返回没有关联的IO操作的“纯”值。 (这就是
return
的目的!)在函数返回
IO ()
的情况下,类型
()
的唯一值是值
()
,因此唯一的选择是
return ()
。对于其他类型为
IO a
的
a
,您需要
return
一些类型为
a
的值。如果希望该选项返回一个值或不返回一个值,则需要输入
IO (Maybe a)
类型或使用
MaybeT
转换器,如下所示。
Maybe
monad中巧妙地表达嵌套计算:
let newUser = encrypted >>= (\x -> Just user { password = x })
IO
monad中。
>>=
)和
return
操作,以及所有do-syntax都可以引用同一单monad中的操作,因此当您执行以下操作时,不必在“ IO模式”和“也许模式”之间切换重新阅读和编写代码。
MaybeT
包导入
transformers
转换器并定义您自己的monad。您可以随意命名,尽管您可能会键入很多,所以我通常使用简短的名称,例如
M
。
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
-- M is the IO monad supplemented with Maybe functionality
type M = MaybeT IO
nothing :: M a
nothing = mzero -- nicer name for failing in M monad
userSignUp
函数:
userSignUp :: Connection -> User -> M ()
userSignUp conn user = do
encrypted <- encryptPassword (password user) -- encrypted :: String
let newUser = user { password = encrypted } -- newUser :: User
insertUser <- createUser conn -- insertUser :: User -> M ()
insertUser newUser
M
monad会确保确保已对
<-
运算符绑定的每个变量进行检查。如果任何步骤返回
Nothing
,则处理将中止。如果某个步骤返回
Nothing
,则
Just x
将自动展开。您通常不必处理(甚至看不到)
x
或
Nothing
。
Just
monad中,并且它们可以返回值(成功)或指示失败,如下所示:
encryptPassword :: String -> M String
encryptPassword pwd = do
epwd <- liftIO $ do putStrLn "Dear System Operator,"
putStrLn $ "Plaintext password was " ++ pwd
putStr $ "Please manually calculate encrypted version: "
getLine
if epwd == "I don't know" then nothing -- return failure
else return epwd -- return success
M
将操作提升到基础IO monad,因此所有IO操作均可用。否则,它们可以返回纯值(通过
liftIO
)或使用
return
(我的
MaybeT
别名)在
nothing
层中发出信号失败。
mzero
转换为
M a
,因此实际上可以从
IO a
运行它)。对于此monad,定义很简单,但是最好定义一个函数,以防您的
main
monad更复杂:
runM :: M a -> IO (Maybe a)
runM = runMaybeT
M
之类的monad运算符或诸如
=<<
之类的应用运算符来模仿一元形式的函数形式。上下文。以下是
<*>
我的monad转换器版本的等效“更多功能”形式。尚不清楚这比上面的命令式“ do-notation”版本更容易理解,并且肯定更难编写。
moreFunctionalUserSignUp :: Connection -> User -> M ()
moreFunctionalUserSignUp conn user
= join $ createUser conn
<*> (setPassword user <$> encryptPassword (password user))
where
setPassword u p = u { password = p }
createUser conn (setPassword user (encryptPassword (password user)))
userSignUp
?什至不问。)
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
-- M is the IO monad supplemented with Maybe functionality
type M = MaybeT IO
nothing :: M a
nothing = mzero -- nicer name for failing in M monad
runM :: M a -> IO (Maybe a)
runM = runMaybeT
data User = User { username :: String, password :: String } deriving (Show)
data Connection = Connection
userSignUp :: Connection -> User -> M ()
userSignUp conn user = do
encrypted <- encryptPassword (password user) -- encrypted :: String
let newUser = user { password = encrypted } -- newUser :: User
insertUser <- createUser conn -- insertUser :: User -> M ()
insertUser newUser
encryptPassword :: String -> M String
encryptPassword pwd = do
epwd <- liftIO $ do putStrLn "Dear System Operator,"
putStrLn $ "Plaintext password was " ++ pwd
putStr $ "Please manually calculate encrypted version: "
getLine
if epwd == "I don't know" then nothing -- return failure
else return epwd -- return success
createUser :: Connection -> M (User -> M ())
createUser conn = do
-- some fake storage
return (\user -> liftIO $ putStrLn $ "stored user record " ++ show user)
main :: IO ()
main = do username <- putStr "Username: " >> getLine
password <- putStr "Password: " >> getLine
let user = User username password
result <- runM (userSignUp Connection user)
case result of
Nothing -> putStrLn "Something failed -- with MaybeT, we can't tell what."
Just () -> putStrLn "Success!"
关于haskell - 如何使用Monad变形金刚来组合不同的(纯净的和不纯净的)monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46649804/
我正在尝试在我的网站上嵌入多个 .svg 文件。只要我使用 Chrome、Firefox 或我目前测试过的任何移动浏览器,一切似乎都运行良好。但是,有一个异常(exception):每当我在 Wind
我正在尝试在我的网站上嵌入多个 .svg 文件。只要我使用 Chrome、Firefox 或我目前测试过的任何移动浏览器,一切似乎都运行良好。但是,有一个异常(exception):每当我在 Wind
是否有某种方法(库或算法)可用于在 java.awt.Shape 或其路径迭代器的两个实例之间进行插值?例如,要在矩形和椭圆之间无缝过渡?或者更一般的 Path2D 情况。 最佳答案 SwingX 中
我试图在动态大小的视频上包含一个 Canvas 元素,该视频将异步加载。在 Canvas 上,用户将能够拖动矩形选择框并调整其大小。 在我的 JS 文件中,我有一个监听器监 window 口,并通过
Closed. This question needs to be more focused。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅关注editing this post一个问题。 去
有没有办法通过 GDAL(使用 Python API)使用移位向量来扭曲图像? 通过移位向量,我的意思是例如。包含以下列的 CSV(或 numpy)文件:starting_x,starting_y,t
我正在创建一个导航按钮。当用户按下它时,按钮的图像应该改变,反射(reflect)它的状态(例如菜单打开/关闭)。我决定为此做一个 morphing-liek 动画。可以用CoreAnimation来
我在 Pandas 中有以下示例数据框。如何获取每个 'Id' 的 'label_weight' 值的最大值并将相应的 'label' 列分配给该 'Id' 在新列 'assgined_label'
文本使我的框变形。 这是我的: This text is deforming the "leftOne" 还有 CSS: .leftOne { float: left;
HTML: Home Services About Us Contact Us CSS: ul { pa
我想在这里得到 openCV 爱好者的帮助。 我想知道关于如何变形 2 个面孔的方向(以及一些建议或代码段),以及一种比率,即第一个面孔的 10% 和第二个面孔的 90%。 我见过像 cvWarpAf
我已经搜索了很长时间,但还没有找到真正的答案,但是,也许我的眼睛上有西红柿,但是真的没有针对 python/MATLAB 的框架可以进行面部扭曲/开箱即用? 一个框架,我在其中放入两张带有特征点的图像
根据material.io float 操作按钮可以变身为操作菜单,如 this .有什么方法可以只使用 Material 库(没有第三方库)吗? 我试过了this库,但它会在菜单关闭后根据底部应用栏
这就是我想用我的 NSOpenGLView 做的事情。目前 NSOpenGLView 覆盖了窗口的整个区域,我想在 NSOpenGLView 顶部添加按钮、nsviews 和图像。我浏览了网页,发现
我正在遍历在 Controller 中定义的集合。 我正在使用基础轨道插件将其转变为轮播。 但是我的HTML被弄乱了,并且破坏了插件,因为它期望获得一定的输出。
我不知道如何使用 BufferedImage 使图像变形。有人能帮我吗 ?我绝对绝望了。感谢您的所有提示。对不起我的英语不好。 | |
这个问题的答案似乎相互矛盾,我很困惑在 Core Data 数据库中存储图像的最佳方式是什么。 This question说可变形,但是this question说要使用二进制数据。 如果我只是想把它
您好,我不确定如何处理有关表单的逻辑。所以,表格很大,我知道有 20 多个字段被认为是“不好的做法”,表格应该最少,但这就是客户想要的,所以不用争论,无论如何表格都会接受订单,但有不同的顺序类型(更具
我正在使用 animator() 在我的应用程序的帧( subview )之间横向滚动 NSScrollView。当动画发生并且我调整 NSWindow 的大小时,整个 NSView 会像这样扭曲:
仍在我的太空入侵者克隆上工作,我想在屏幕底部添加可破坏的基地: 我已经弄清楚如何通过让炸弹和盾牌相互接触来修改盾牌的外观,然后在 didBegincontact 中,从炸弹爆炸的 mask 和盾牌的当
我是一名优秀的程序员,十分优秀!