Identity Monad - Haskell 中的行为差异?
Identity Monad - Behaviour difference in Haskell?
我最近一直在 Haskell 中研究 Monads(对于这一切,我还是一个相对初学者)。 Identity Monad
.
我遇到了一些有趣的行为(或者至少对我来说很有趣)
如果我写下面的函数:
let f = \x -> Identity 2 >>= \y -> x * y
然后做 :t
我得到 f :: Num b => Identity b -> Identity b
。它推断 x 是一个 Identity (Num b)
。我可以使用 6
调用该函数并得到结果 12
.
但是,如果我像这样对 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
因此我需要明确地 return Maybe
或使用 return
。所以我这样做:let g = \x -> Just 2 >>= \y -> return $ x * y
.
一切正常。但是后来我想知道 Identity
monad 发生了什么。
首先,我尝试添加显式 return 类型,如下所示:
let f = \x -> Identity 2 >>= \y -> Identity $ x * y
然后又做了 :t
,我得到了 f :: Num b => b -> Identity b
。这正是我第一次期待的。
这让我想知道它如何在没有 Identity $
的情况下处理 x + y
如果它推断 x
和 y
被包裹在一个
Identity
。所以我尝试了以下方法:
Identity 5
+ Identity 6
结果为 11
Identity 5
+ 6
结果又是 11
不过,我尝试用 Maybe
做同样的事情,就像这样
Just 5
+ Just 6
Just 5
+ 6
我收到以下错误:
<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
我试过 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
我想知道是否有人可以阐明为什么 Identity
monad 行为与 Maybe
不同?
还有可能使用 FlexibleContexts
来获得与 Maybe
monad 相同的行为吗?到目前为止,我还无法让它工作。
这是因为 Identity
有一个 Num
实例而 Maybe
没有(您可以在 GHCi 中使用 :i
或查看 in the Hackage documentation).
因此,当您有 \x -> Identity 2 >>= \y -> x * y
时,*
实际上是 Identity a
的 Num
实例中的 *
(其中 a
本身就是一个 Num
实例,例如 Int
或 Double
等)。
此外,Haskell 中的数字文字是多态的:5 :: Num a => a
,因此它们可以像任何 Num
实例一样运行,而不是仅限于特定实例(如 Int
或 Double
)。这就是当您尝试类似 Identity 5 + 6
时发生的情况。 6
被推断为 Num a => Identity a
类型,因为 (+) :: Num a => a -> a -> a
.
你可以更清楚地看到这一点:
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
我最近一直在 Haskell 中研究 Monads(对于这一切,我还是一个相对初学者)。 Identity Monad
.
如果我写下面的函数:
let f = \x -> Identity 2 >>= \y -> x * y
然后做 :t
我得到 f :: Num b => Identity b -> Identity b
。它推断 x 是一个 Identity (Num b)
。我可以使用 6
调用该函数并得到结果 12
.
但是,如果我像这样对 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
因此我需要明确地 return Maybe
或使用 return
。所以我这样做:let g = \x -> Just 2 >>= \y -> return $ x * y
.
一切正常。但是后来我想知道 Identity
monad 发生了什么。
首先,我尝试添加显式 return 类型,如下所示:
let f = \x -> Identity 2 >>= \y -> Identity $ x * y
然后又做了 :t
,我得到了 f :: Num b => b -> Identity b
。这正是我第一次期待的。
这让我想知道它如何在没有 Identity $
的情况下处理 x + y
如果它推断 x
和 y
被包裹在一个
Identity
。所以我尝试了以下方法:
Identity 5
+ Identity 6
结果为 11
Identity 5
+ 6
结果又是 11
不过,我尝试用 Maybe
做同样的事情,就像这样
Just 5
+ Just 6
Just 5
+ 6
我收到以下错误:
<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
我试过 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
我想知道是否有人可以阐明为什么 Identity
monad 行为与 Maybe
不同?
还有可能使用 FlexibleContexts
来获得与 Maybe
monad 相同的行为吗?到目前为止,我还无法让它工作。
这是因为 Identity
有一个 Num
实例而 Maybe
没有(您可以在 GHCi 中使用 :i
或查看 in the Hackage documentation).
因此,当您有 \x -> Identity 2 >>= \y -> x * y
时,*
实际上是 Identity a
的 Num
实例中的 *
(其中 a
本身就是一个 Num
实例,例如 Int
或 Double
等)。
此外,Haskell 中的数字文字是多态的:5 :: Num a => a
,因此它们可以像任何 Num
实例一样运行,而不是仅限于特定实例(如 Int
或 Double
)。这就是当您尝试类似 Identity 5 + 6
时发生的情况。 6
被推断为 Num a => Identity a
类型,因为 (+) :: Num a => a -> a -> a
.
你可以更清楚地看到这一点:
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