来自document:
when :: (Monad m) => Bool -> m () -> m ()
when p s = if p then s else return ()
when
函数采用布尔参数和单位()
类型的monadic计算,并仅在布尔参数为True
时执行计算。
===
作为Haskell的新手,我的问题是对我来说m ()
是一些" void"数据,但这里文件提到它是计算。是因为Haskell的懒惰吗?
答案 0 :(得分:6)
懒惰没有参与其中。
m
/ Monad部分通常称为计算。
最好的例子可能是m = IO
:
查看putStrLn "Hello" :: IO ()
- 这是一项计算,运行时会将"Hello"
打印到您的屏幕上。
此计算没有结果 - 因此返回类型为()
现在写的时候
hello :: Bool -> IO ()
hello sayIt =
when sayIt (putStrLn "Hello")
然后hello True
是一个计算,运行时会打印"Hello"
;而hello False
是一个计算,运行时根本不会做任何事情。
现在将它与getLine :: IO String
进行比较 - 这是一个计算,在运行时会提示您输入并将输入作为String
返回 - 这就是返回类型为{{1 }}
这有帮助吗?
答案 1 :(得分:2)
对我而言“m()”是一些“无效”数据
这有点意义,因为计算是一种特殊的数据。它与懒惰无关 - 它与背景有关。
我们以State
为例。类型的函数,比如Haskell中的s -> ()
只能生成一个值。但是,类型s -> ((), s)
的函数是在s
上执行某些转换的常规函数。您遇到的问题是,您只查看()
部分,而s -> s
部分则隐藏。这是State
的重点 - 隐藏状态的传递。
因此,State s ()
可以简单地转换为s -> ((), s)
并返回,它仍然是Monad
(计算),它产生的值为...... ()
。
如果我们看看实际用途,现在:
(flip runState 10) $ do
modify (+1)
此表达式生成((), Int)
的元组;隐藏了Int
部分
它将修改状态,为其添加1。但它产生的中间值()
适合您的when
:
when (5 > 3) $ modify (+1)
答案 2 :(得分:2)
Monads显然是抽象的和数学的,所以关于它们的直观陈述通常是用相当模糊的语言制作的。因此,monadic类型的值通常被非正式标记为"计算," "动作"或(不常见)"命令"因为这是一个类比,有时可以帮助我们推理它们。但是当你深入挖掘时,使用这种方式时这些都是空话;最终他们的意思是"提供Monad
界面的某种类型的价值。"
我喜欢"动作"更好的是,让我顺其自然。在Haskell中使用该单词的直觉是:语言区分函数和 actions :
a -> b
。IO a
。
IO ()
类型的操作会产生无趣的结果值,因此它既可以是无操作(return ()
),也可以是仅有趣的操作,因为它的副作用。 Monad
然后是允许您将动作粘合在一起形成复杂动作的界面。
这一切都非常直观,但是当你尝试将它应用于IO
类型以外的许多单子时,它会变得相当紧张。例如,列表是monad:
instance Monad [] where
return a = [a]
as >>= f = concatMap f as
"行动"或"计算" monad列表是......列表。如何列出一个"动作"或者"计算"?在这种情况下,类比相当弱,不是吗?
所以我说这是最好的建议:
Monad
法律以及与Monad
一起使用的各种功能的定义。