类型类的应用性成分定律 [英] The composition law of Applicative in the Typeclassopedia

查看:86
本文介绍了类型类的应用性成分定律的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 Typeclassopedia ,而我在应用程序"部分遇到了麻烦.我想我(已经)知道了,但是我想看看我的理解是否正确.

I am reading Typeclassopedia and I was having trouble in the section on Applicatives. I think I (sort of) have it figured out but I want to see if my understanding is correct.

直到组成法之前,适用法律才有意义.我只是无法解析它的右侧:

The laws for applicative made sense right up until the Composition law. I just couldn't parse the right-hand side of this:

u <*> (v <*> w) = pure (.) <*> u <*> v <*> w

所以,我启动了GHCI并进行了一些实验.

So, I fired up GHCI and ran some experiments.

Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just 34
Just 37

所以这验证了法律,但我仍然不明白.我尝试了一些变体,看能否获得一些见识:

So this verifies the law, but I still didn't understand it. I tried some variations to see if I could get some insight:

Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just (+3) <*> Just 34

<interactive>:26:1: error:
    * Non type-variable argument in the constraint: Num (b -> b)
      (Use FlexibleContexts to permit this)
    * When checking the inferred type
        it :: forall b. (Num (b -> b), Num b) => Maybe b

那么,合成只对两个功能起作用,而对三个不起作用?我不明白为什么.

So, composition works for two functions but not for three? I didn't understand why.

然后我验证了<*>的工作方式是否符合我认为的简单表达方式:

I then verified that <*> worked as I thought it would for a simple expression:

Prelude> Just (+1) <*> Just 1
Just 2

但是,以下操作无效:

Prelude>  Just (+1) <*> Just (+2) <*> Just 34

<interactive>:15:2: error:
    * Non type-variable argument in the constraint: Num (b -> b)
      (Use FlexibleContexts to permit this)
    * When checking the inferred type
        it :: forall b. (Num (b -> b), Num b) => Maybe b

因此,应用程序与合成不同.我以为Just (+2) <*> Just 34会导致Just 36,而Just (+1) <*> Just 36会导致Just 37.需要组合运算符(.),但它仅对两个函数有效.我只是不明白为什么需要它或它如何工作.

So, application isn't the same as composition. I had thought that Just (+2) <*> Just 34 would have resulted in Just 36 and Just (+1) <*> Just 36 would have resulted in Just 37. The composition operator, (.), is needed, but it only works for two functions. I just didn't understand why it was needed or how it worked.

然后,为了将更多的污垢倒入水中,我尝试了以下操作:

And, just to throw more dirt into this water, I tried the following:

Prelude> Just (,) <*> Just 2

失败,因为没有用于结果的Show实例.所以我尝试了:

which failed because there was no instance of Show for the result. So I tried:

Prelude> :t Just (,) <*> Just 2
Just (,) <*> Just 2 :: Num a => Maybe (b -> (a, b))

这给了我一些见识.我需要传递第二个值来获取返回的tuple.我试过了:

This gave me a bit of insight. I needed to pass a second value to get a tuple returned. I tried:

Prelude> Just (,) <*> Just 2 Just 34

但是失败了,错误消息确实并没有帮助我弄清楚错误在哪里.因此,查看以上代码的类型,我意识到它就像我输入Just (2, )一样(无论如何也是如此).所以,我尝试了:

but that failed, and the error message really didn't help me figure out just where the error was. So, looking at the type of the above code I realized that it was the same as if I had entered Just (2, ) (or something like it, anyway). So, I tried:

Prelude> Just (,) <*> Just (2) <*> Just 34
Just (2,34)

实际上,我对此功能感到惊讶.但令我惊讶的是,理解的萌芽(我认为).

I was actually surprised that this worked. But in that surprise came the germ of understanding (I think).

我回到Typeclassopedia中的(<*>)的定义,发现它被定义为 left 关联的.在此之前,我什至没有考虑过关联性.因此,上面的表达式实际上将评估如下内容:

I went back to the definition of (<*>) in Typeclassopedia and discovered it is defined as left associative. I hadn't even considered associativity before this. So the above expression would actually evaluate something like this:

Prelude> Just (,) <*> Just (2) <*> Just 34
-- Apply the 2 as the first parameter of (,) leaving a function
-- that takes the second parameter
Just (2,) <*> Just 34
-- Now apply the 34 as the parameter to the resulting function
Just (2,34)

如果这是正确的,那么起作用的《合成法》的示例将评估如下:

If this is correct then the example of the Composition law that worked evaluates like this:

Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just 34
pure (+1 . ) <*> Just (+2) <*> Just 34
pure (+1 . +2) <*> Just 34
Just 37

这也解释了为什么不能以这种方式组合三个功能:

This also explains why three functions cannot be composed this way:

Prelude> pure (.) <*> Just (+1) <*> Just (+2) <*> Just (+3) <*> Just 34
pure (+1 . ) <*> Just (+2) <*> Just (+3) <*> Just 34
pure (+1 . +2) <*> Just (+3) <*> Just 34

并且,在这一点上,我们有一个组合函数,期望Num类型类的一个实例,但相反,是将其传递给函数,该函数会失败.

And, at this point we have a composed function expecting an instance of the Num typeclass but are, instead, passing it a function, which fails.

以类似的方式:

Prelude>  Just (+1) <*> Just (+2) <*> Just 34

失败,因为<*>不是复合文件,并且正在尝试将一个函数(+2)应用于另一个函数(+1),并遇到类型约束.

fails because <*> isn't composition and is trying to apply a function, (+2) to another function, (+1), and running into a type constraint.

那么,我的直觉在这里正确吗?我终于想通了吗?还是我的(有点)受过教育的猜测仍然不合时宜?

So, is my intuition correct here? Have I finally figured this out? Or is my (somewhat) educated guess still off base?

推荐答案

这只是一种情况,即未正确应用替换规则,并且忘记了括号在这些替换中的重要性(尽管其中有些可以稍后删除).该规则应表示为

This is just a case of not applying the substitution rule correctly, and forgetting the importance of parentheses in these substitutions (although some of them can be dropped later). The rule should be expressed as

u <*> (v <*> w) == (pure (.) <*> u <*> v) <*> w

然后

Just (+1) <*> (Just (+2) <*> Just 34)
    -- u = Just (+1)
    -- v = Just (+2)
    -- w = Just 34
 => (pure (.) <*> u <*> v) <*> w
 => (pure (.) <*> Just (+1) <*> Just (+2)) <*> Just 34

要在此之上添加另一层,您必须使用另一个pure (.):

To add another layer on this, you have to use another pure (.):

Just (+3) <*> (Just (+1) <*> (Just (+2) <*> Just 34))
    -- u = Just (+3)
    -- v = Just (+1)
    -- w = Just (+2) <*> Just 34
 => (pure (.) <*> u <*> v) <*> w
 => pure (.) <*> Just (+3) <*> Just (+1) <*> (Just (+2) <*> Just 34)

如果您想从第一阶段开始使用pure表格,就可以了

If you wanted to work off of the pure form from the first stage, you'd have

Just (+3) <*> ((pure (.) <*> Just (+1) <*> Just (+2)) <*> Just 34)
    -- u = Just (+3)
    -- v = pure (.) <*> Just (+1) <*> Just (+2)
    -- w = Just 34
 => (pure (.) <*> u <*> v) <*> w
 => pure (.) <*> Just (+3) <*> (pure (.) <*> Just (+1) <*> Just (+2)) <*> Just 34

恐怕这还不如人们所希望的那么漂亮.

Which isn't nearly as pretty as one would hope, I'm afraid.

这篇关于类型类的应用性成分定律的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆