我可能一直错误地认为 Haskell 比现在更懒惰,但我想知道是否有办法两全其美……
Data.Monoid并Data.Semigroup定义 的两个变体First。幺半群版本对最左边的非空值建模,而半群版本只是对最左边的值建模。
这适用于纯值,但考虑不纯值:
x = putStrLn "x" >> return 42
y = putStrLn "y" >> return 1337
Run Code Online (Sandbox Code Playgroud)
这两个值都具有类型Num a => IO a。IO a是一个Semigroup实例,当a是:
instance Semigroup a => Semigroup (IO a)
-- Defined in `Data.Orphans'
Run Code Online (Sandbox Code Playgroud)
这意味着可以组合两个IO (First a)值:
Prelude Data.Semigroup Data.Orphans> fmap First x <> fmap First y
x
y
First {getFirst = 42}
Run Code Online (Sandbox Code Playgroud)
我们可以看到,虽然双方x并y产生各自的副作用,即使y是从来没有要求。
这同样适用于Data.Monoid …