Haskell函数组成了两个二进制函数?

时间:2021-12-25 22:04:43

I'm working my way through 20 Intermediate Haskell exercises and I got stuck on exercise 13:

我正在通过20次中级Haskell练习,我被困在练习13:

-- Exercise 13
-- Relative Difficulty: 6
apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = error "todo"

where the Misty Typeclass is essentially the Monad Typeclass and is implemented like this:

其中Misty Typeclass基本上是Monad Typeclass,并且实现如下:

class Misty m where
    banana :: (a -> m b) -> m a -> m b
    unicorn :: a -> m a

I gave in to my curiosity and found the solution to this exercise online as

我满足了我的好奇心,并在网上找到了这个练习的解决方案

apple = banana . flip furry'

where furry' is a version of liftM implemented as

其中furry'是一个实现的liftM版本

furry' f mi = banana (\x -> unicorn (f x)) mi

What I don't understand is the use of function composition (.) on two binary functions (namely banana and the flipped furry'), if someone could walk through the evaluation of this I think that would help me a lot.

我不明白的是在两个二元函数(即香蕉和翻转的毛茸茸')上使用函数组合(。),如果有人可以通过评估我认为这对我有很大帮助。

1 个解决方案

#1


Let's start step by step. Misty typeclass is given:

让我们一步一步开始吧。给出了错误的类型类:

class Misty m where 
  banana :: (a -> m b) -> m a -> m b 
  unicorn :: a -> m a

Also furry' is already solved in an earlier problem in those exercises:

在这些练习的早期问题中,“毛茸茸的”已经解决了:

furry' :: Misty m => (a -> b) -> m a -> m b
furry' f mi = banana (\x -> unicorn (f x)) mi

Now you have apple function which you have to define:

现在你有了必须定义的apple函数:

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = error "todo"

Now just try to follow the type signature. Assume you are defining apple like this:

现在只需尝试按照类型签名。假设您正在定义这样的苹果:

apple xs ys

xs will have type of m a

ys will have type of m (a -> b)

Now can you see the relation between the above types and furry' ? So you have to somehow apply xs and ys to furry' Now since it's second parameter is m a which you already have in xs, you can use flip to obtain it:

现在你能看到上述类型与毛茸茸之间的关系吗?所以你必须以某种方式将xs和ys应用于毛茸茸的'现在,因为它的第二个参数是你已经在xs中拥有的,你可以使用flip来获取它:

flip furry' :: m a -> (a -> b) -> m b

翻转毛茸茸':: m a - >(a - > b) - > m b

So you can apply xs to the first parameter of it and you will have the following type signature:

因此,您可以将xs应用于它的第一个参数,您将拥有以下类型签名:

(flip furry') xs :: (a -> b) -> m b ------- Equation 1

(翻转毛茸茸')xs ::(a - > b) - > m b -------等式1

Any guess on how to apply it ys? Try to unify the above type signature with the first parameter of banana :

有关如何应用它的任何猜测?尝试将上述类型签名与banana的第一个参数统一起来:

That will give you:

那会给你:

a ~ (a -> b)
m b ~ (m b)

So, the type signature of banana gets transformed from

因此,香蕉的类型签名会从中转化而来

banana :: (a -> m b) -> m a -> m b

to

banana :: ((a -> b) -> m b) -> m (a -> b) -> m b 

Now from Equation (1) we know that (flip furry') xs type signature matches the first parameter of banana and ys matches the second parameter of banana. And that gives you the definition of apple:

现在从等式(1)我们知道(翻转毛茸茸')xs类型签名匹配banana的第一个参数,ys匹配banana的第二个参数。这给了你苹果的定义:

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple xs ys = banana ((flip furry') xs ) ys

which can be expressed in pointfree manner as:

可以无点的方式表达为:

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = banana . flip furry'

#1


Let's start step by step. Misty typeclass is given:

让我们一步一步开始吧。给出了错误的类型类:

class Misty m where 
  banana :: (a -> m b) -> m a -> m b 
  unicorn :: a -> m a

Also furry' is already solved in an earlier problem in those exercises:

在这些练习的早期问题中,“毛茸茸的”已经解决了:

furry' :: Misty m => (a -> b) -> m a -> m b
furry' f mi = banana (\x -> unicorn (f x)) mi

Now you have apple function which you have to define:

现在你有了必须定义的apple函数:

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = error "todo"

Now just try to follow the type signature. Assume you are defining apple like this:

现在只需尝试按照类型签名。假设您正在定义这样的苹果:

apple xs ys

xs will have type of m a

ys will have type of m (a -> b)

Now can you see the relation between the above types and furry' ? So you have to somehow apply xs and ys to furry' Now since it's second parameter is m a which you already have in xs, you can use flip to obtain it:

现在你能看到上述类型与毛茸茸之间的关系吗?所以你必须以某种方式将xs和ys应用于毛茸茸的'现在,因为它的第二个参数是你已经在xs中拥有的,你可以使用flip来获取它:

flip furry' :: m a -> (a -> b) -> m b

翻转毛茸茸':: m a - >(a - > b) - > m b

So you can apply xs to the first parameter of it and you will have the following type signature:

因此,您可以将xs应用于它的第一个参数,您将拥有以下类型签名:

(flip furry') xs :: (a -> b) -> m b ------- Equation 1

(翻转毛茸茸')xs ::(a - > b) - > m b -------等式1

Any guess on how to apply it ys? Try to unify the above type signature with the first parameter of banana :

有关如何应用它的任何猜测?尝试将上述类型签名与banana的第一个参数统一起来:

That will give you:

那会给你:

a ~ (a -> b)
m b ~ (m b)

So, the type signature of banana gets transformed from

因此,香蕉的类型签名会从中转化而来

banana :: (a -> m b) -> m a -> m b

to

banana :: ((a -> b) -> m b) -> m (a -> b) -> m b 

Now from Equation (1) we know that (flip furry') xs type signature matches the first parameter of banana and ys matches the second parameter of banana. And that gives you the definition of apple:

现在从等式(1)我们知道(翻转毛茸茸')xs类型签名匹配banana的第一个参数,ys匹配banana的第二个参数。这给了你苹果的定义:

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple xs ys = banana ((flip furry') xs ) ys

which can be expressed in pointfree manner as:

可以无点的方式表达为:

apple :: (Misty m) => m a -> m (a -> b) -> m b
apple = banana . flip furry'