我想我找到了 "non-existent monad"
I think I found a "non-existent monad"
我发现了 Haskell 的一个奇怪特征,这让我相信我的思考方式是错误的。我认为在 Haskell 中应该有一些 "non-existent" monad。这是因为以下原因。
Prelude> return 1
1
Prelude> return 1 >>= \x -> if even x then return True else return False
False
>>=
是 m a -> (a -> m b) -> m b
类型,其中 m
可以是任何 monad。我的理论是这样的:由于 return 1
的计算结果仅为 1
,因此 return 1
可以被认为是 1
提升到包含在 中的值"non-existent" 单子。 Haskell 捕获了这个事实并评估了整个表达式
return 1 >>= \x -> if even x then return True else return False
到 False
因为它必须产生一个 "non-existent False
" 这仅仅是 False
.
但是,我以前从未听说过这样的 "non-existent" monad。
我确信我以错误的方式对它进行了理论化,因为如果 "non-existent 1
" 只是 1
,则以下表达式必须类型一致,但事实并非如此。它是上述版本的修改版本。
1 >>= \x -> if even x then return True else return False
<interactive>:57:1: error:
• Could not deduce (Integral a0)
from the context: (Monad m, Integral a, Num (m a))
bound by the inferred type for ‘it’:
forall (m :: * -> *) a. (Monad m, Integral a, Num (m a)) => m Bool
at <interactive>:57:1-56
The type variable ‘a0’ is ambiguous
• In the ambiguity check for the inferred type for ‘it’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
it :: forall (m :: * -> *) a.
(Monad m, Integral a, Num (m a)) =>
m Bool
所以,我的理论肯定有矛盾。我错过了什么?
return 1
不仅仅是 1
。你认为的 "non-existent monad" 实际上是 IO
。当您使用 return 1
时,GHCi 假设您的意思是 IO
,然后帮助执行 IO 表达式并显示结果。 1 >>= ...
出现类型错误,因为 1
不是 monad。
作为@bradrn mentions ,一般来说GHCi会自动运行你给它的任何IO a
值,然后打印出这个值它 returns;如果你给 GHCi 一个非 IO
类型的值,它只会打印那个值(如果可以的话)。
顺便说一句,有一个名为 Identity
的 monad,正如您所说,它本质上确实像 "non-existent monad" 一样工作,因为 return x
与 x
同构不管你放什么。但是,它不会自动使用;您需要手动包装和解包才能使用它。
我发现了 Haskell 的一个奇怪特征,这让我相信我的思考方式是错误的。我认为在 Haskell 中应该有一些 "non-existent" monad。这是因为以下原因。
Prelude> return 1
1
Prelude> return 1 >>= \x -> if even x then return True else return False
False
>>=
是 m a -> (a -> m b) -> m b
类型,其中 m
可以是任何 monad。我的理论是这样的:由于 return 1
的计算结果仅为 1
,因此 return 1
可以被认为是 1
提升到包含在 中的值"non-existent" 单子。 Haskell 捕获了这个事实并评估了整个表达式
return 1 >>= \x -> if even x then return True else return False
到 False
因为它必须产生一个 "non-existent False
" 这仅仅是 False
.
但是,我以前从未听说过这样的 "non-existent" monad。
我确信我以错误的方式对它进行了理论化,因为如果 "non-existent 1
" 只是 1
,则以下表达式必须类型一致,但事实并非如此。它是上述版本的修改版本。
1 >>= \x -> if even x then return True else return False
<interactive>:57:1: error:
• Could not deduce (Integral a0)
from the context: (Monad m, Integral a, Num (m a))
bound by the inferred type for ‘it’:
forall (m :: * -> *) a. (Monad m, Integral a, Num (m a)) => m Bool
at <interactive>:57:1-56
The type variable ‘a0’ is ambiguous
• In the ambiguity check for the inferred type for ‘it’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
When checking the inferred type
it :: forall (m :: * -> *) a.
(Monad m, Integral a, Num (m a)) =>
m Bool
所以,我的理论肯定有矛盾。我错过了什么?
return 1
不仅仅是 1
。你认为的 "non-existent monad" 实际上是 IO
。当您使用 return 1
时,GHCi 假设您的意思是 IO
,然后帮助执行 IO 表达式并显示结果。 1 >>= ...
出现类型错误,因为 1
不是 monad。
作为@bradrn mentions IO a
值,然后打印出这个值它 returns;如果你给 GHCi 一个非 IO
类型的值,它只会打印那个值(如果可以的话)。
顺便说一句,有一个名为 Identity
的 monad,正如您所说,它本质上确实像 "non-existent monad" 一样工作,因为 return x
与 x
同构不管你放什么。但是,它不会自动使用;您需要手动包装和解包才能使用它。