简体   繁体   English

Identity Monad - Haskell 中的行为差异?

[英]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 .这让我想知道如果它推断xy被包裹在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 aNum实例的* (其中a本身就是一个Num实例,例如IntDouble等)。

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实例一样运行,而不受限于特定实例(如IntDouble )。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM