为什么 (&) :: a -> (a -> b) -> b 不被视为 Monad?

Why is (&) :: a -> (a -> b) -> b not treated as Monad?

在数学上,函数应用的二元运算是endo-Functor/Monad。

pipe :: (a -> b) -> a -> b
pipe = \f -> \a -> f a

(|>) :: a -> (a -> b) -> b
(|>) = flip pipe

infixl 1 |>

称为pipeline-operator,在Haskell中,预定义为

https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Function.html#v:-38-

(&) :: a -> (a -> b) -> b

monadTestPipe :: IO ()
monadTestPipe = do
  "Monad Laws========" & print
  let i = id

  let a = (3 :: Int)
  let f = (\a -> a + 1) >>> i
  let g = (\a -> a * 2) >>> i
  let m = f a -- 4
  "---------------------------------" & print
  do
    "-- Left/Center/Right identity" & print
    let lft = a & i & f
    let ctr = a & f -- = m
    let rit = a & f & i
    ---------------------------------
    lft & print -- 4
    ctr & print -- 4
    rit & print -- 4
    "---------------------------------" & print
  do
    "-- Associativity" & print
    -- m = f a -- 4
    (m & f) & g
      & print -- 10 = (4+1)x2
    m & (\x -> f x & g)
      & print -- 10
    "---------------------------------" & print

为什么管道操作 (&) :: a -> (a -> b) -> b 在 Haskell 中未被视为(至少未集成)Monad?

或者,可以这么说,我从未在任何 Haskell wiki 或书籍中读过。

编辑:我想让我的问题尽可能简洁,以防止问题扩散,但是

class Applicative m => Monad m where
  (>>=) :: m a -> (a -> m b) -> m b
  return :: a -> m a

>>=只是Haskell中Monad类型class的符号,而&可以集成到>>=,因为&是数学意义上的 monad 运算符。

returnid :: a -> a

它被视为 monad(特别是 identity monad)的绑定操作(又名 (>>=)),只是不是直接的。由于类型系统的工作方式,您必须使用包装器:您不能将 type Id a = a 之类的类型同义词作为 Monad 的实例,并且没有 type-level lambda。

type Id a = a简单描述了一个同义词:aId a是同一类型。

你不能有像

这样的实例
instance Monad Id

使用上述 Id 的定义,因为 Id 在本质上与 type-level lambda \a -> a 相同(如果 Haskell), 和 Haskell doesn't have this kind of type-level lambda, since they would make Haskell's type system undecidable.

然而,这正是创建 newtype 结构的主要原因之一。它创建了一个新类型(顾名思义),它包装了旧类型,并且只存在于 type-level 处区分旧类型和新类型。它们甚至具有相同的运行时表示。您可以阅读更多关于两者之间的区别 .

在这种情况下,包装器称为 Identity