我一直认为哈斯克尔的do-notation只是单曲的糖(>>=)。然后我偶然发现了这个例子,我不知道这里使用的是哪一种单体,或者是否甚至有一种:
rollDieThreeTimes :: (Die, Die, Die)
rollDieThreeTimes = do
let s = mkStdGen 0
(d1, s1) = randomR (1, 6) s
(d2, s2) = randomR (1, 6) s1
(d3, _) = randomR (1, 6) s2
(intToDie d1, intToDie d2, intToDie d3)
intToDie :: Int -> Die
...我的问题:
在这个例子中,
do-notation的基础上吗?如果没有,是否有某种特殊形式的do-notation允许使用这种格式的let-statements而没有单曲?如果存在单曲,则是do-notation转换成>>=表单?发布于 2022-07-06 23:25:38
应该始终在一元上下文中使用do。但是,如果在do-block中只有一个表达式,那么它就会对该表达式进行解析,因此不存在对>>=的引用,也不会产生Monad约束。
所以你可以写
do let x = a
y = b
foo这相当于
let x = a
y = b
in foo但实际上,你应该只写后者。
我还没有读过HPFFP,谷歌告诉我,这可能是你从这本书中学到的。它来自于关于状态的章节,似乎作者将其介绍为一个简单的无状态示例,然后将其添加到其中。也许他们选择这种不寻常的结构是出于教学上的原因,例如,为了保持它类似于以后的版本,使用一元绑定来代替let绑定。
发布于 2022-07-18 02:14:55
了解do-表示法的一件重要事情是,它的规则是在类型检查之前应用的。这些规则(大致)是:
do { x; y } ==> x >> do { y } (规则应用于recursively)do {x <- a; b } ==> a >>= \x -> do { b }do {{pat} <- a; b } ==> a >>= \x ->大小写x {pat} -> do {b}_ -> fail“模式匹配失败”)
do { let {decls}; b } ==> let {decls} in do { b }do { a } ==> a最后这两条规则在这里是很重要的--任何没有(隐式)分号的表达式本身都会变成它自己。因此,只要不使用前两条规则,代码中就可以有任何类型的表达式,而不需要任何单一的表达式。遵循这些规则,您的代码将从
rollDieThreeTimes :: (Die, Die, Die)
rollDieThreeTimes = do
let s = mkStdGen 0
(d1, s1) = randomR (1, 6) s
(d2, s2) = randomR (1, 6) s1
(d3, _) = randomR (1, 6) s2
(intToDie d1, intToDie d2, intToDie d3)至
rollDieThreeTimes :: (Die, Die, Die)
rollDieThreeTimes =
let s = mkStdGen 0
(d1, s1) = randomR (1, 6) s
(d2, s2) = randomR (1, 6) s1
(d3, _) = randomR (1, 6) s2
in (intToDie d1, intToDie d2, intToDie d3)然后进行类型检查。
https://stackoverflow.com/questions/72890778
复制相似问题