用< =<构成单调函数 [英] Composing Monadic Functions with `<=<`

查看:119
本文介绍了用< =<构成单调函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解< =< 函数:

  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 ms 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 Maybes 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

这篇关于用&lt; =&lt;构成单调函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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