[英]Identity Monad - Behaviour difference in Haskell?
I have recently been playing around with Monads in Haskell (still a relative beginner with all this).我最近一直在玩 Haskell 中的 Monads(在这方面仍然是一个相对的初学者)。 I came across some interesting behaviour (or at least interesting to me) with the
Identity Monad
.我在
Identity Monad
遇到了一些有趣的行为(或者至少对我来说很有趣)。
If I write the following function:如果我编写以下函数:
let f = \\x -> Identity 2 >>= \\y -> x * y
and then do :t
I get f :: Num b => Identity b -> Identity b
.然后做
:t
我得到f :: Num b => Identity b -> Identity b
。 It is inferring that x is an Identity (Num b)
.推断 x 是一个
Identity (Num b)
。 I am able to call the function with 6
and I get the result 12
.我可以用
6
调用该函数,然后得到结果12
。
However if I try the same with Maybe
like so:但是,如果我像这样尝试与
Maybe
一样:
let g = \\x -> Just 2 >>= \\y -> x * y
<interactive>:2096:5: error:
• Non type-variable argument in the constraint: Num (Maybe b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
g :: forall b. Num (Maybe b) => Maybe b -> Maybe b
I therefore need to explicitly return Maybe
or use return
.因此,我需要明确返回
Maybe
或使用return
。 So I do: let g = \\x -> Just 2 >>= \\y -> return $ x * y
.所以我这样做:
let g = \\x -> Just 2 >>= \\y -> return $ x * y
。
Everything works fine.一切正常。 However then I got to wondering what is happening with the
Identity
monad.但是后来我开始想知道
Identity
monad 发生了什么。
Firstly I tried adding the explicit return type like so:首先,我尝试添加显式返回类型,如下所示:
let f = \\x -> Identity 2 >>= \\y -> Identity $ x * y
and then did :t
again and I got f :: Num b => b -> Identity b
.然后又做了
:t
,我得到了f :: Num b => b -> Identity b
。 Which is what I was expecting the first time around.这是我第一次期待的。
Which made me wonder about how it was able to handle x + y
without Identity $
if it was inferring x
and y
to be wrapped inside an Identity
.这让我想知道如果它推断
x
和y
被包裹在Identity
它如何能够在没有Identity $
情况下处理x + y
。 So I tried the following:所以我尝试了以下方法:
Identity 5
+ Identity 6
with the result being 11
Identity 5
+ Identity 6
结果为11
Identity 5
+ 6
with the result being 11
again Identity 5
+ 6
结果又是11
However it I try the same with Maybe
like so然而它我尝试同样的
Maybe
像这样
Just 5
+ Just 6
Just 5
+ Just 6
Just 5
+ 6
Just 5
+ 6
I get the following error:我收到以下错误:
<interactive>:2116:1: error:
• Non type-variable argument in the constraint: Num (Maybe a)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Num (Maybe a), Num a) => Maybe a
I have tried FlexibleContexts
but I just got the following error:我已经尝试过
FlexibleContexts
但我刚刚收到以下错误:
<interactive>:2134:1: error:
• No instance for (Num (Maybe a0)) arising from a use of ‘it’
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
I was wondering if someone could shed a little light on why the Identity
monad behaviour is different to Maybe
?我想知道是否有人可以解释为什么
Identity
monad 行为与Maybe
不同?
Also is it possible to use FlexibleContexts
to get the same behaviour with the Maybe
monad?是否可以使用
FlexibleContexts
来获得与Maybe
monad 相同的行为? I haven't been able to get it to work as of yet.到目前为止,我还无法让它发挥作用。
This is because Identity
has a Num
instance and Maybe
does not (you can see the instances of a type by using :i
in GHCi or looking in the Hackage documentation ).这是因为
Identity
有一个Num
实例,而Maybe
没有(您可以通过在 GHCi 中使用:i
或查看Hackage 文档来查看类型的实例)。
So, when you have \\x -> Identity 2 >>= \\y -> x * y
, that *
is actually the *
from the Num
instance for Identity a
(where a
is itself a Num
instance, like Int
or Double
, etc).因此,当您拥有
\\x -> Identity 2 >>= \\y -> x * y
,该*
实际上是来自Identity a
的Num
实例的*
(其中a
本身就是一个Num
实例,例如Int
或Double
等)。
Additionally, numeric literals in Haskell are polymorphic: 5 :: Num a => a
, so they can behave as any Num
instance rather than being restricted to a specific one (like Int
or Double
).此外,Haskell 中的数字文字是多态的:
5 :: Num a => a
,因此它们可以像任何Num
实例一样运行,而不受限于特定实例(如Int
或Double
)。 That is what's happening when you try something like Identity 5 + 6
.当您尝试
Identity 5 + 6
类的东西时,就会发生这种情况。 The 6
is inferred to have type Num a => Identity a
, since (+) :: Num a => a -> a -> a
.推断
6
类型为Num a => Identity a
,因为(+) :: Num a => a -> a -> a
。
You can see this more explicitly:您可以更明确地看到这一点:
ghci> :t 5
5 :: Num p => p
ghci> 5 :: Identity Int
Identity 5
ghci> 5 :: Maybe Int
<interactive>:12:1: error:
• No instance for (Num (Maybe Int)) arising from the literal ‘5’
• In the expression: 5 :: Maybe Int
In an equation for ‘it’: it = 5 :: Maybe Int
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.