Haskell 身份单子-哈斯克尔的行为差异?

Haskell 身份单子-哈斯克尔的行为差异?,haskell,monads,identity,Haskell,Monads,Identity,我最近一直在Haskell玩Monads(这方面我还是一个相对的初学者)。我在Identity Monad中遇到了一些有趣的行为(或者至少对我来说很有趣) 如果我编写以下函数: 让f=\x->Identity 2>=\y->x*y <interactive>:2096:5: error: • Non type-variable argument in the constraint: Num (Maybe b) (Use FlexibleContexts to p

我最近一直在Haskell玩Monads(这方面我还是一个相对的初学者)。我在
Identity Monad
中遇到了一些有趣的行为(或者至少对我来说很有趣)


如果我编写以下函数:

让f=\x->Identity 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
然后做
:t
我得到
f::Num b=>Identity b->Identity b
。推断x是一个
标识(numb)
。我可以用
6
调用函数,并得到结果
12

但是,如果我对
尝试同样的方法,可能会像这样:

让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
我已经尝试了
FlexibleContexts
,但我刚刚遇到以下错误:

<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
<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
:2134:1:错误:
•没有因使用“it”而产生的(Num(可能是a0))实例
•在“print”的第一个参数中,即“it”
在交互式GHCi命令的stmt中:打印它

我想知道是否有人能解释一下为什么
身份
单子行为不同于
可能


还可以使用
FlexibleContexts
获得与
Maybe
monad相同的行为吗?到目前为止,我还无法让它工作。

这是因为
标识
有一个
Num
实例,而
可能没有(您可以通过在GHCi中使用
:I
或查看来查看类型的实例)

因此,当你有
\x->Identity 2>=\y->x*y
时,
*
实际上是
Num
实例中的
*
对于
Identity a
(其中
a
本身就是
Num
实例,比如
Int
Double
,等等)

此外,Haskell中的数字文字是多态的:
5::Num a=>a
,因此它们可以作为任何
Num
实例,而不限于特定的实例(如
Int
Double
)。这就是当您尝试类似于
Identity 5+6
的方法时所发生的情况。由于
(+)::Num a=>a->a
,因此推断
6
具有类型
Num 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
ghci>:t5
5::nump=>p
ghci>5::标识Int
身份5
ghci>5::可能是整数
:12:1:错误:
•没有由文字“5”产生的(Num(可能是Int))实例
•在表达式中:5::Maybe Int
在“it”的等式中:it=5::可能是Int

这很奇怪,我不希望
Identity
有num实例。为什么?以这种速度,我们为什么不为所有应用程序添加num实例呢?@luqui,我不知道。这特别奇怪,因为我认为
IdentityT
没有这些实例。尽管如此,我不知道你为什么只限于应用程序,不管怎样。。。我认为
Num
法则应该(真空地)通过类似
datavoidwitharga
(其中没有构造函数)的东西来满足。@luquiapplicative实际上不够强大,无法保证一个
Num
法则,即
absx*signum x==x
(想想
[]
,或者
解析器
)我想上一次我想到这一点时,我发现
x*>x=x
是一个合理的规则,可以区分那些基于
Applicative
Num
实例遵守法律的应用程序和那些不遵守法律的应用程序,但我不知道有哪个类将其作为法律。@BenjaminHodgson(还有德弗尔和丹尼尔·瓦格纳):如果这算是有趣的话,可能会有
的出现。
x*>x=x
是King和Wadler在书中称之为幂等单子的结果。(注意,我们可能想要调整这个名称——不仅因为该属性直接推广到应用程序,而且因为“幂等单子”BenjaminHodgson大多数“zippy”应用程序(如duplode提到的
可能
ZipList
,以及其他在
()
上做类似于zip的事情的容器类型)都满足这一规律。