Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中,如何在存在Maybe值的情况下替换成对元素?_Haskell_Monads_Traversable - Fatal编程技术网

在Haskell中,如何在存在Maybe值的情况下替换成对元素?

在Haskell中,如何在存在Maybe值的情况下替换成对元素?,haskell,monads,traversable,Haskell,Monads,Traversable,考虑Haskell中的这两个函数: replace_snd :: b -> Maybe (a, b) -> Maybe (a, b) replace_snd y' (Just (x, y)) = Just (x, y') replace_snd _ Nothing = Nothing inject_snd :: Maybe b -> (a, b) -> Maybe (a, b) inject_snd (Just b') (a, b) = Just (a, b') inj

考虑Haskell中的这两个函数:

replace_snd :: b -> Maybe (a, b) -> Maybe (a, b)
replace_snd y' (Just (x, y)) = Just (x, y')
replace_snd _ Nothing = Nothing

inject_snd :: Maybe b -> (a, b) -> Maybe (a, b)
inject_snd (Just b') (a, b) = Just (a, b')
inject_snd Nothing _ = Nothing
replace\u snd
替换对中的第二个元素,如果没有对,则不返回任何内容:

> replace_snd 30 (Just (1, 2))
Just (1,30)
> replace_snd 30 Nothing
Nothing
inject\u snd
替换第二个元素,如果没有替换,则不返回任何内容:

> inject_snd (Just 30) (1, 2)
Just (1,30)
> inject_snd Nothing (1, 2)
Nothing

也考虑它们的对称对应符<代码> RePATIOFFST,<代码> CujTuffFST ,作用于一对的第一个元素:

replace_fst :: a -> Maybe (a, b) -> Maybe (a, b)
replace_fst x' (Just (x, y)) = Just (x', y)
replace_fst _ Nothing = Nothing

inject_fst :: Maybe a -> (a, b) -> Maybe (a, b)
inject_fst (Just a') (a, b) = Just (a', b)
inject_fst Nothing _ = Nothing
我的问题是:这四个函数中,哪一个可以使用内置函数(如一元运算符)编写得更紧凑?怎么做

例如,我意识到
inject\u snd
只是
(mapM.const)
,因为
可能是
单子
(,)a)
可遍历的

> (mapM . const) (Just 30) (1, 2)
Just (1,30)
> (mapM . const) Nothing (1, 2)
Nothing
其他三个功能是否有类似的紧凑等价物

import Control.Arrow

replaceSnd = fmap . second . const
或者
fmap。fmap。const
,它不需要
箭头
导入。。。但是我不喜欢
(a,)
functor,这不会扩展到
replaceFst
。然而,使用
箭头
同样简单:

replaceFst = fmap . first . const
inject
s有点笨拙,但仍然可以通过应用程序操作符部分轻松完成:

injectSnd y t = fmap (($ t) . second . const) y
injectFst y t = fmap (($ t) . first . const) y
同样,您可以用
fmap
替换
second
,但请不要这样做

这也可以写出来

injectSnd = flip $ \t -> fmap $ ($ t) . second . const
当然,如果您同意翻转签名,则无需进行
flip

injectSnd' :: (a, b) -> Maybe b -> Maybe (a, b)
injectSnd' t = fmap $ ($ t) . second . const

它们都可以以紧凑的方式重写。例如,
replace\u fst
(或
replace\u snd
)是以下情况的特例:

或更紧凑:

import Control.Arrow(first)

replace_fst :: Functor f => a -> f (a, b) -> f (a, b)
replace_fst = fmap . first . const
至于
inject\u fst
,这是相同的,只是我们现在将
fmap
放在第一项上,因此:

import Control.Arrow(first)

inject_fst :: Functor f => f a -> (a, b) -> f (a, b)
inject_fst c x = fmap (($ x) . first . const) c
因此,我们在
c
上执行
fmap
ing,其中,如果
c
Just y
,我们将返回
Just(first(const y)x)
,否则如果
c
Nothing
则返回
Nothing

例如:

Prelude Control.Arrow> replace_fst 0 Nothing
Nothing
Prelude Control.Arrow> replace_fst 0 (Just (1,2))
Just (0,2)
Prelude Control.Arrow> inject_fst Nothing (1,2)
Nothing
Prelude Control.Arrow> inject_fst (Just 0) (1,2)
Just (0,2)

这些功能不仅适用于
可能
,而且适用于列表
[]
,等等。

感谢您快速而有用的回复<代码>fmap。fmap。常数=fmap。(顺便说一句,我个人很欣赏
(a,)
函子,将其视为“用
a
装饰的值”。我知道这有点像一场圣战。@d呃,那是
作者
。我对
(a,)
单子的问题,甚至对
(a,)的问题
traversable,就是元组应该直观地表现对称,但事实并非如此。相比之下,没有人期望
Writer
在其参数之间是对称的。感谢您快速而有用的回答!对
箭头的概括似乎对您没有帮助。您可以从
数据中使用
首先
。Bifunctor
而不是使用
(,)
以外的双触发器。
import Control.Arrow(first)

inject_fst :: Functor f => f a -> (a, b) -> f (a, b)
inject_fst c x = fmap (($ x) . first . const) c
Prelude Control.Arrow> inject_fst Nothing (1,2)
Nothing
Prelude Control.Arrow> inject_fst (Just 0) (1,2)
Just (0,2)