7

只是在寻找以下组合如何工作的解释:

(=<<) . return

在哪里

(=<<) ::       (a -> m b) -> m a -> m b
return :: a -> m a
(.) :: (b -> c) -> (a -> b) -> a -> c

最终类型:

GHCi> :t (=<<) . return
(=<<) . return :: Monad m => m b -> m a -> m b

我无法理解如何将ma(a -> mb)匹配,即。如何将简单类型的返回结果应用于(=<<)期望函数类型的第一个参数?

4

2 回答 2

7

解释是:

  1. return是(也许出乎意料地)与你的不同的单子=<<
  2. 它使用的 monad 是 reader monad (->) r

编译器尝试将 的结果return :: c -> m' c与 的第一个参数统一(a -> m b) -> m a -> m b,因此与统一 。唯一的可能是一些读者单子。接下来,它尝试统一with (converted to the prefix notation) ,这通过设置to和to 来解决。所以,统一后,编译器得到最通用的可能类型m' ca -> m bm'(->) rr(->) r c(->) a (m b)racm b

return :: (m b) -> ((->) a (m b))

或以通常的中缀表示法

return :: (m b) -> (a -> m b)

也可以看看:


编辑:要定义一个 monad,我们需要一个(部分应用的)kind 类型 * -> *。这些几乎总是部分应用的数据构造函数,但在这种特殊情况下,我们将->其视为一个类型运算符,它接受 2 个类型参数并创建一个新类型(函数类型)。所以对于任何给定的类型r,部分应用的表达式(->) r都是一种类型* -> *。事实证明,有一种直接的方法可以描述对它的 monad 操作。请参阅Control.Reader monad 以及 解释它的这篇文章。for 的 monad 操作的Reader实现方式与 for 完全相同(->),唯一的区别是Reader将操作包装成不同的数据类型。

于 2012-08-19T09:10:25.007 回答
1

我又一次,用涂鸦,把东西并排放置以帮助视觉理解:

g = ((=<<) . return)   {-

((=<<) . return) x y 
         ===   (=<<)    (return x)    y               return :: a' -> m' a'
               (=<<) :: (a -> m b) -> m a -> m b      return x :: m' a' , x :: a'
                          m'  a'                      m' ~ ((->) a) , a' ~ m b 

return x === const x             -- instance Monad ((->) a) where return = const
g x y === y >>= (\_ -> x) === y >> x   (!!)
-}

g :: m b -> m a -> m b

所以事实证明(并且可能从类型签名中很明显)g === flip (>>),:

Prelude> ((=<<).return) [1] "xyz"   -- ===  (=<<) (const [1]) "xyz" 
                                    -- ===  "xyz" >>= const [1]
                                    -- ===  "xyz" >> [1]
                                    -- ===  (>> [1]) "xyz"
[1,1,1]
于 2012-08-20T09:21:33.603 回答