我要查找的签名是(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。