在Haskell中,当我们使用do块时,它如何确定要使用哪个monad?

时间:2017-07-25 10:31:29

标签: haskell

我们知道do块只是语法糖。但是,它如何确定它所处的monadic背景?假设我们不在do块中的任何位置使用{{1}}运算符。

2 个答案:

答案 0 :(得分:10)

它使用相同的通用类型类机制,用于确定要使用哪个+,甚至用于文字的数字类型。那是,

之类的东西
 do
    return True

不会使用它应该使用的特定monad,而只是分配类型Monad m => m Bool。这个约束表示do-block具有任何 m Bool的类型m,它恰好实现了Monad类型类。此外,每当使用此块时,将从其使用的上下文推断出特定实例。

如果我们使用与特定Monad绑定的运算符,则会强制该类型变得更具体。例如,如果我们使用modify :: (a -> a) -> State s a -> State s ()(我在这里为了示例而简化类型),那么这将强制块具有类型State s ...。通常,Haskell将找出最常用的类型,并使用类型类约束来确保所讨论的类型实现适当的操作。

答案 1 :(得分:7)

也许有些"实用"示例将有所帮助:

foo1 = do
  print 5
  return 7
-- print belongs to the IO monad. This whole thing is in IO.

foo2 x = do
  writeTVar x 7
  return 11
-- writeTVar belongs to the STM monad. This whole thing is in STM.

foo3 = do
  let x = 5
  [1, 2, 3, 4]
-- Last line is a list expression. This whole thing is in the list monad.

foo4 = do
  put 7
  return 9
-- put is in the State monad. This whole thing is in the state monad.

foo5 = do
  x <- magic1
  y <- magic2
  return (x, y)
-- This is in whatever monad magic1 and magic2 are in.

foo6 = do
  return 13
-- Doesn't mention any monad. Works for ALL POSSIBLE MONADS!

foo7 abc def = do
  x <- abc
  y <- def
  return (x, y)
-- Runs in whatever monad abc and def run in.
-- By passing different arguments, you can CHANGE which monad that is!