为什么 (&) :: 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 运算符。
return
是 id :: a -> a
它被视为 monad(特别是 identity monad)的绑定操作(又名 (>>=)
),只是不是直接的。由于类型系统的工作方式,您必须使用包装器:您不能将 type Id a = a
之类的类型同义词作为 Monad
的实例,并且没有 type-level lambda。
type Id a = a
简单描述了一个同义词:a
和Id 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
。
在数学上,函数应用的二元运算是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 运算符。
return
是 id :: a -> a
它被视为 monad(特别是 identity monad)的绑定操作(又名 (>>=)
),只是不是直接的。由于类型系统的工作方式,您必须使用包装器:您不能将 type Id a = a
之类的类型同义词作为 Monad
的实例,并且没有 type-level lambda。
type Id a = a
简单描述了一个同义词:a
和Id 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
。