在Maybe类型上应用函数? [英] apply function on Maybe types?

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

问题描述

Haskell和我无法弄清楚如何将一个函数(a - > b)应用到列表[也许a]并得到[也许b]

  maybeX ::(a  - > b) - > [也许a]  - > [也许b] 

函数应该和map完全相同,应用函数f在Maybe语句的列表中,如果它只是它返回我af只是,如果它是一个Nothing只是一个Nothing。
就像下面的例子,我想在以下列表的每个元素上添加+5:

 只是2,没有,只是3] 

并获得

  [Just 6,Just 7,Nothing,Just 8] 

真的试图想象这个,我尝试了很多,但它总是好像是我不知道这种Maybe数据类型的工作方式。
感谢您的帮助!

解决方案

我们首先定义如何处理单个 Maybe ,然后我们将它扩展到一个完整的列表。

  mapMaybe ::(a  - > b) - >也许是 - >也许b 
mapMaybe f Nothing = Nothing
mapMaybe f(Just x)= Just(fx)

如果 Maybe 包含一个值,则 mapMaybe 应用 f ,如果它不包含值,那么我们只返回一个空的 Maybe



但是我们有一个 可能 s,所以我们需要应用 mapMaybe

  mapMaybes ::(a  - > b) - > [也许a]  - > [也许b] 
mapMaybes f ms = [mapMaybe f m | m < - ms]

在这里,我使用list comprehension来评估 mapMaybe fm 对于 ms 中的每个 m






现在是更先进的技术。将函数应用于容器中的每个值的模式都由 Functor 类型类捕获。

  class Functor f where 
fmap ::(a - > b) - > f a - > fb

类型 f 是一个 Functor 如果你可以编写一个函数,该函数从 a b ,然后将该函数应用于 f 完整的 a s以获得 f 完整的 b s。例如, [] Maybe 都是 Functor s :

  instance Functor Maybe where 
fmap f Nothing = Nothing
fmap f(Just x)= Just (fx)

实例Functor []其中
fmap f xs = [fx | x < - xs]

也许'这个版本的 fmap 与我上面写的 mapMaybe 相同, [] 的实现使用list comprehension将 f 应用于列表中的每个元素。



现在,要写 mapMaybes ::(a - > b) - > [也许a] - > [也许是b] ,你需要使用 [] 的版本 fmap ,然后使用 Maybe 版本操作单个 Maybe
$ b $ $ p $ mapMaybes ::(a - > b) - > $ c> fmap

[也许a] - > [也许b]
mapMaybes f ms = fmap(fmap f)ms
- 或者:
mapMaybes = fmap。 fmap

请注意,我们实际上调用了两个不同的 fmap 这里的实现。外部的是 fmap ::(也许a - >也许b) - > [也许a] - > [也许是b] ,它派发给 [] Functor 实例。内部的是(a - > b) - >也许是 - >也许b






另外一个附录 - 虽然这是相当深奥的,所以不要担心如果你不了解这里的一切。



这个 fmap s的链我想给你一些我觉得很酷的东西。 style( fmap .fmap .fmap ... )是深入了解结构的多个层的常用技巧。每个 fmap 都有一个类型(a - > b) - > (fa - > fb),所以当你用(。)编写它们时,你正在构建一个更高阶的函数。

  fmap :: Functor g => (f a  - > f b) - > (g(f a) - > g(f b))
fmap :: Functor f => (a - > b) - > (f a - > f b)
- so ...
fmap。 fmap ::(Functor f,Functor g)=> (a - > b) - > g(f a) - > g(fb)

所以如果你有函子的函数(函数...),那么 n fmap s可让您映射结构级别 n 的元素。 Conal Elliot称这种风格为语义编辑组合器



这个技巧也适用于 traverse ::(Traversable t,Applicative f)=> (a - > f b) - > (ta - > f(tb)),这是一种有效的 fmap

  traverse ::(...)=> (t a  - > f(t b)) - > (s(t a) - > f(s(t b)))
遍历::(...)=> (a - > f b) - > (t a - > f(t b))
- so ...
遍历。遍历::(...)=> (a - > f b) - > s(t a) - > f(s(tb))

(我省略了 = < / code>因为我用完了水平空间。)所以,如果你有遍历遍历(可遍历...),你可以对 n 只需写遍历 n 次即可。像这样构成遍历是镜头背后的基本思想。


New to Haskell and I can't figure out how apply a function (a -> b) into a list [Maybe a] and get [Maybe b]

maybeX:: (a -> b) -> [Maybe a] -> [Maybe b]

The function is supposed to do the exact same thing as map, apply the function f on a list of Maybe statements and if it Just it returns me a f Just and if it's a Nothing just a Nothing. Like the following example I want to add +5 on every Element of the following List :

[Just 1,Just 2,Nothing,Just 3]

and get

[Just 6,Just 7,Nothing,Just 8]

Really trying to figure this and I tried a lot but it always seems like it is something that I'm not aware of in the way of which this Maybe datatype works.. Thanks for your help!

解决方案

Let's start by defining how to act on a single Maybe, and then we'll scale it up to a whole list.

mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe f Nothing = Nothing
mapMaybe f (Just x) = Just (f x)

If the Maybe contains a value, mapMaybe applies f to it, and if it doesn't contain a value then we just return an empty Maybe.

But we have a list of Maybes, so we need to apply mapMaybe to each of them.

mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b]
mapMaybes f ms = [mapMaybe f m | m <- ms]

Here I'm using a list comprehension to evaluate mapMaybe f m for each m in ms.


Now for a more advanced technique. The pattern of applying a function to every value in a container is captured by the Functor type class.

class Functor f where
    fmap :: (a -> b) -> f a -> f b

A type f is a Functor if you can write a function which takes a function from a to b, and applies that function to an f full of as to get an f full of bs. For example, [] and Maybe are both Functors:

instance Functor Maybe where
    fmap f Nothing = Nothing
    fmap f (Just x) = Just (f x)

instance Functor [] where
    fmap f xs = [f x | x <- xs]

Maybe's version of fmap is the same as the mapMaybe I wrote above, and []'s implementation uses a list comprehension to apply f to every element in the list.

Now, to write mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b], you need to operate on each item in the list using []'s version of fmap, and then operate on the individual Maybes using Maybe's version of fmap.

mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b]
mapMaybes f ms = fmap (fmap f) ms
-- or:
mapMaybes = fmap . fmap

Note that we're actually calling two different fmap implementations here. The outer one is fmap :: (Maybe a -> Maybe b) -> [Maybe a] -> [Maybe b], which dispatches to []'s Functor instance. The inner one is (a -> b) -> Maybe a -> Maybe b.


One more addendum - though this is quite esoteric, so don't worry if you don't understand everything here. I just want to give you a taste of something I think is pretty cool.

This "chain of fmaps" style (fmap . fmap . fmap ...) is quite a common trick for drilling down through multiple layers of a structure. Each fmap has a type of (a -> b) -> (f a -> f b), so when you compose them with (.) you're building a higher-order function.

fmap        :: Functor g              =>             (f a -> f b) -> (g (f a) -> g (f b))
fmap        :: Functor f              => (a -> b) -> (f a -> f b)
-- so...
fmap . fmap :: (Functor f, Functor g) => (a -> b)          ->         g (f a) -> g (f b)

So if you have a functor of functors (of functors...), then n fmaps will let you map the elements at level n of the structure. Conal Elliot calls this style "semantic editor combinators".

The trick also works with traverse :: (Traversable t, Applicative f) => (a -> f b) -> (t a -> f (t b)), which is a kind of "effectful fmap".

traverse            :: (...) =>               (t a -> f (t b)) -> (s (t a) -> f (s (t b)))
traverse            :: (...) => (a -> f b) -> (t a -> f (t b))
-- so...
traverse . traverse :: (...) => (a -> f b)            ->           s (t a) -> f (s (t b))

(I omitted the bits before the => because I ran out of horizontal space.) So if you have a traversable of traversables (of traversables...), you can perform an effectful computation on the elements at level n just by writing traverse n times. Composing traversals like this is the basic idea behind the lens library.

这篇关于在Maybe类型上应用函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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