用< =<构成单调函数 [英] Composing Monadic Functions with `<=<`
问题描述
我试图理解< =<
函数:
ghci的> :t(<= <)
(< =<):: Monad m => (b→m c)→> (a - > m b) - > a - > mc
据我所知,我给它2个函数,一个 a
,然后我得到 mc
。
那么,为什么不这个例子编译?
import Control.Monad
f :: a - >也许
f = \ x - >只需x
g :: a - > [a]
g = \ x - > [x]
foo :: Monad m => a - > m c
foo x = f <=< gx
对于 foo 3
仅仅3
作为结果。
但是我得到这个错误:
File.hs:10:15:
无法匹配预期的类型`a0 - >也许c0'
的实际类型为`[a]'
在调用`g'的返回类型中
可能的原因:`g'应用于太多参数
在'(<= <)'的第二个参数中,即`g x'
在表达式中:f <=< g x失败,模块加载:无。
这里有两个错误。 b
$ b
首先,如果它们共享相同的monad,则(<= <)
仅构成monadic函数。换句话说,你可以用它来编写两个 Maybe
函数:
(<= <)::(b→>可能c)→> (a - >可能b) - > (a - > Maybe c)
...或两个列表函数:
(<=<)::(b - > [c]) - > (a - > [b]) - > (a - > [c])
...但是您无法撰写列表功能,以这种方式运作。原因是当你有这样的类型签名时:
(< =<):: Monad m => (b→m c)→> (a - > m b) - > (a - > mc)
...编译器将确保所有 m
s必须匹配。
第二个错误是您忘记了加上你的作文。您可能想要的是:
(f <=
...如果您省略括号,编译器会像这样解释它:
f <=< (gx)
修复函数的一个简单方法就是定义一个帮助函数,将可能
s列表:
mayToList :: Maybe a - > [a]
maybeToList Nothing = []
mayToList(只是a)= [a]
这个函数实际上有以下两个很好的属性:
mayToList。返回=返回
mayToList。 (f <=< g)=(maybeToList.f)< =< (maybeToList。g)
...如果您将 (maybeToList。)
类似于 fmap
并且处理(< =<)
类似于(。)
和 return
类似于 id
然后解决方案变成:
$ $ $ $ $ $ $ $ $(mayToList.f < =
I'm trying to understand the <=<
function:
ghci> :t (<=<)
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
As I understand it, I give it 2 functions and an a
, and then I'll get an m c
.
So, why doesn't this example compile?
import Control.Monad
f :: a -> Maybe a
f = \x -> Just x
g :: a -> [a]
g = \x -> [x]
foo :: Monad m => a -> m c
foo x = f <=< g x
For foo 3
, I would expect Just 3
as a result.
But I get this error:
File.hs:10:15:
Couldn't match expected type `a0 -> Maybe c0'
with actual type `[a]'
In the return type of a call of `g'
Probable cause: `g' is applied to too many arguments
In the second argument of `(<=<)', namely `g x'
In the expression: f <=< g x Failed, modules loaded: none.
There are two errors here.
First, (<=<)
only composes monadic functions if they share the same monad. In other words, you can use it to compose two Maybe
functions:
(<=<) :: (b -> Maybe c) -> (a -> Maybe b) -> (a -> Maybe c)
... or two list functions:
(<=<) :: (b -> [c]) -> (a -> [b]) -> (a -> [c])
... but you cannot compose a list function and maybe function this way. The reason for this is that when you have a type signature like this:
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)
... the compiler will ensure that all the m
s must match.
The second error is that you forgot to parenthesize your composition. What you probably intended was this:
(f <=< g) x
... if you omit the parentheses the compiler interprets it like this:
f <=< (g x)
An easy way to fix your function is just to define a helper function that converts Maybe
s to lists:
maybeToList :: Maybe a -> [a]
maybeToList Nothing = []
maybeToList (Just a) = [a]
This function actually has the following two nice properties:
maybeToList . return = return
maybeToList . (f <=< g) = (maybeToList . f) <=< (maybeToList . g)
... which are functor laws if you treat (maybeToList .)
as analogous to fmap
and treat (<=<)
as analogous to (.)
and return
as analogous to id
.
Then the solution becomes:
(maybeToList . f <=< g) x
这篇关于用< =<构成单调函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!