有没有一种很好的方法来打开元组中的Maybe值



我要查找的签名是(Maybe a, b) -> (a, b),hoogle不返回任何结果。我可以很容易地将自己写为

import Data.Maybe (fromJust)
fromJustTuple :: (Maybe a, b) -> (a, b)
fromJustTuple (a, b) = (fromJust a, b)

上下文是我在Map上使用updateLookupWithKey,在那里我可以保证我查询的密钥存在。我可以说

let (Just x, myMap') = updateLookupWithKey f k myMap

,但我必须禁用incomplete-uni-patterns,这是我不想做的。

备份一点,这可能是XY问题。我很高兴听到这些,并了解到一种不同的、更地道的方法。

将我自己的评论复制到一个答案中:

您可以将fromJustTuple写为first fromJust(其中first来自Control.Arrow(

first具有类型签名:

first :: Arrow a => a b c -> a (b, d) (c, d) 

但对你来说,忽略";箭头";第一个的一部分,并假装它专门用于功能,这就赋予了它类型:

first :: (b -> c) -> (b, d) -> (c, d)

也就是说:它映射在元组的第一个元素上。


最终,我认为你的问题是,尽管你;可以保证[你]查询的密钥存在";,你无法向类型系统证明这一点,所以除非你能改变这一点否则你将不得不依赖像fromJust这样的不安全函数,或者得到不完整的模式匹配警告。

我认为困难的原因是updateLookupWithKey不是合适的工具。为什么不使用alterF

import Data.Map (Map)
import qualified Data.Map as M
import Data.Maybe
update :: (Ord k, Num a) => (a -> a) -> k -> Map k a -> (a, Map k a)
update f = M.alterF (old -> let new = f (fromMaybe 0 old) in (new, Just new))
incr :: (Ord k, Num a) => k -> Map k a -> (a, Map k a)
incr = update (+1)
decr :: (Ord k, Num a) => k -> Map k a -> (a, Map k a)
decr = update (subtract 1)

现在,Maybe的唯一外观是当密钥实际上不在Map中时进行覆盖,在这种情况下,它默认将关联值设置为0。

最新更新