Monad没有包装值?
  大部分monad解释都使用monad包装值的例子。  例如, Maybe a ,其中a类型变量是包装的。  但我想知道monads不会包装任何东西。 
对于一个人为的例子,假设我有一个可以控制的现实世界的机器人,但没有传感器。 也许我想要这样控制它:
robotMovementScript :: RobotMonad ()
robotMovementScript = do
  moveLeft 10
  moveForward 25
  rotate 180
main :: IO ()
main = 
  liftIO $ runRobot robotMovementScript connectToRobot
  在我们的虚拟API中, connectToRobot返回物理设备的某种句柄。  这个连接成为RobotMonad的“上下文”。  因为我们与机器人的连接永远不会向我们发回值,所以monad的具体类型始终是RobotMonad () 。 
一些问题:
RobotMonad - 从不包装价值?  或者这是否违背了monads的基本概念? <>连接机器人控制动作。  虽然do标记看起来更具可读性。 RobotMonad () ?   我已经看过Data.Binary.Put作为例子。  它似乎与我所想的相似(或者相同?)。  但它也涉及作家monad和Builder monoid。  考虑到那些额外的皱纹和我目前的技能水平,我认为Put monad可能不是最具启发性的例子。 
编辑
我实际上并不需要构建一个像这样的机器人或API。 这个例子完全是人为的。 我只是需要一个永远不会有理由将价值从monad中提取出来的例子。 所以我并没有要求解决机器人问题的最简单方法。 相反,这个关于没有内在价值的单子的思想实验是试图更好地理解单子。
TL;没有包装价值的DR Monad并不是很特别,你可以将所有相同的功率建模为一个列表。
  有一种叫做Free monad的东西。  这很有用,因为它在某种意义上是所有其他monad的优秀代表 - 如果您在某些情况下可以了解Free monad的行为,那么您可以很好地了解Monad的行为。 
它看起来像这样
data Free f a = Pure a
              | Free (f (Free f a))
  每当f是Functor , Free f就是Monad 
instance Functor f => Monad (Free f) where
  return       = Pure
  Pure a >>= f = f a
  Free w >>= f = Free (fmap (>>= f) w)
  那么当a总是()时会发生什么?  我们不需要a参数了 
data Freed f = Stop 
             | Freed (f (Freed f))
  显然,这不能再是Monad了,因为它有错误的类型(类型)。 
Monad f ===> f       :: * -> *
             Freed f :: *
  但是,我们仍然可以定义类似Monad被摆脱的IC功能上它a零件 
returned :: Freed f
returned = Stop
bound :: Functor f                          -- compare with the Monad definition
   => Freed f -> Freed f                    -- with all `a`s replaced by ()
   -> Freed f
bound Stop k      = k                       Pure () >>= f = f ()
bound (Freed w) k =                         Free w  >>= f =
  Freed (fmap (`bound` k) w)                  Free (fmap (>>= f) w)
-- Also compare with (++)
(++) []     ys = ys
(++) (x:xs) ys = x : ((++) xs ys)
  看起来是(而且是!)一个Monoid 。 
instance Functor f => Monoid (Freed f) where
  mempty  = returned
  mappend = bound
  Monoid可以通过列表来初始化。  我们使用列表Monoid的通用属性,如果我们有函数Monoid m => (a -> m)那么我们可以将列表[a]变成m 。 
convert :: Monoid m => (a -> m) -> [a] -> m
convert f = foldr mappend mempty . map f
convertFreed :: Functor f => [f ()] -> Freed f
convertFreed = convert go where
  go :: Functor f => f () -> Freed f
  go w = Freed (const Stop <$> w)
所以就机器人而言,我们只需使用一系列动作即可脱身
data Direction = Left | Right | Forward | Back
data ActionF a = Move Direction Double a
               | Rotate Double a
               deriving ( Functor )
-- and if we're using `ActionF ()` then we might as well do
data Action = Move Direction Double
            | Rotate Double
robotMovementScript = [ Move Left    10
                      , Move Forward 25
                      , Rotate       180
                      ]
  现在,当我们将它转换为IO我们明确地将这个方向列表转换为Monad并且我们可以看到,将我们的初始Monoid发送给Freed ,然后将Freed f当作Free f ()并将其解释为初始Monad关于我们想要的IO操作。 
  但很明显,如果你不使用“包装”值,那么你并没有真正使用Monad结构。  你可能只是有一个列表。 
我会试着对这些部分给出部分答案:
RobotMonad - 从不包装价值?  或者这是否违背了monads的基本概念? <>连接机器人控制动作。  虽然符号似乎更具可读性。 RobotMonad () ? monad的核心操作是monadic绑定操作
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
这意味着一个行动取决于(或可能取决于)前一个行动的价值。 因此,如果你有一个固有的有时并不带有可被视为价值的东西的概念(即使是复杂的形式,如继续单子), monad也不是一个好的抽象概念 。
  如果我们放弃>>=我们基本上只剩下Applicative 。  它也允许我们编写行动,但它们的组合不能依赖于前面的值。 
  还有一个Applicative实例不带值,如您所示:Data.Functor.Constant。  它的类型a行为必须是一个monoid,以便它们可以组合在一起。  这似乎是最接近你想法的概念。  当然,我们可以直接使用Monoid而不是Constant 。 
  也就是说,也许更简单的解决方案是拥有一个monad RobotMonad a ,它具有一个值( RobotMonad a ,它本质上与Writer monad是同构的)。  并声明runRobot需要RobotMonad () ,所以它可以只执行没有值的脚本: 
runRobot :: RobotMonad () -> RobotHandle -> IO ()
  这将允许您使用do记号,并与机器人脚本中值的工作。  即使机器人没有传感器,能够传递值也常常有用。  并且扩展这个概念可以让你创建一个monad变换器,比如RobotMonadT ma (类似于WriterT ) 
runRobotT :: (Monad m) => RobotMonadT m () -> RobotHandle -> IO (m ())
也许
runRobotT :: (MonadIO m) => RobotMonadT m () -> RobotHandle -> m ()
这将是一个强大的抽象,可以让你将机器人动作与任意monad结合起来。
好吧
data Useless a = Useless
instance Monad Useless where
  return = const Useless
  Useless >>= f = Useless
但正如我所表明的那样,这不是有用的。
  你想要的是Writer monad,它把monoid包装成monad,所以你可以使用符号。 
