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'