koyama41
もし本当に「リストの長さが違っていて長い方のリストの後ろの方に Nothing がある場合も Nothing」にしたいなら、先にそれぞれ sequence してから liftA2 zip して fmap fromList すればよさそうですね
fmap fromList $ liftA2 zip (sequence keys) (sequence values)
fromList <$> liftA2 zip (sequence keys) (sequence values)
と書きたいか^^;fromList <$> (zip <$> sequence keys <*> sequence values)
ですね、はい^^;some :: (Ord key) => [Maybe key] -> [Maybe value] -> Maybe (M.Map key value) some keys values = M.fromList <$> zipWithM f keys values where f :: Maybe key -> Maybe value -> Maybe (key, value) f mkey mvalue = (,) <$> mkey <*> mvalue
foldM step (M.empty,values) keys >>= (\(acc,l) -> acc <$ sequence_ l) where step (!acc, []) mkey = (acc, []) <$ mkey step (!acc, mval:vals) mkey = (,vals) <$> (M.insert <$> mkey <*> mval <*> pure acc)
あ、ちなみに今回の僕のケースだとkeysとvaluesでサイズが違う場合があります
pairWith f (Just x) (Just y) = Just (f x y) pairWith _ _ _ = Nothing pair = pairWith (,) left = pairWith const -- right = pairWith (flip const) cross f g (x, y) = (f x, g y) some :: [Maybe a] -> [Maybe b] -> Maybe [(a, b)] some xs ys = sequence ps `left` sequence rs where dummy = repeat (Just undefined) (ps, rs) = go xs ys [] go [] ys ps = (ps, zipWith pair dummy ys) go xs [] ps = (ps, zipWith pair xs dummy) go (x:xs) (y:ys) ps = cross (pair x y:) id $ go xs ys ps
Just undefined
で詰めるんですね^^;(<:>) = liftA2 (:) (<.>) = liftA2 (,) left = liftA2 const some :: [Maybe a] -> [Maybe b] -> Maybe [(a,b)] some (x:xs) (y:ys) = (x <.> y) <:> some xs ys some [] ys = Just [] `left` sequence ys some xs [] = Just [] `left` sequence xs
<,>
が作りたかったけどカンマは無理だった…import Data.Map (Map) import qualified Data.Map as M some :: Ord k => ([Maybe k], [Maybe v]) -> Maybe (Map k v) some = hylo phi z psi where z = Just M.empty phi (Just Nothing, _) _ = Nothing phi (_, Just Nothing) _ = Nothing phi _ Nothing = Nothing phi (Nothing, _) _ = z phi (_, Nothing) _ = z phi (Just (Just k), Just (Just v)) (Just m) = Just (M.insert k v m) psi ([], []) = Nothing psi (k:ks, []) = Just ((Just k, Nothing), (ks, [])) psi ([], v:vs) = Just ((Nothing, Just v), ([], vs)) psi (k:ks,v:vs) = Just ((Just k, Just v), (ks,vs)) hylo :: (b -> c -> c) -> c -> (a -> Maybe (b, a)) -> a -> c hylo phi z psi x = case psi x of Nothing -> z Just (y, x') -> phi y (hylo phi z psi x')
buildMap :: Ord k => ([Maybe k], [Maybe v]) -> Maybe (Map k v) buildMap = hylo phi psi where z = Just M.empty phi Nil = z phi (Cons (Just Nothing, _) _ ) = Nothing phi (Cons (_, Just Nothing) _ ) = Nothing phi (Cons _ Nothing) = Nothing phi (Cons (Nothing, _) _ ) = z phi (Cons (_, Nothing) _ ) = z phi (Cons (Just (Just k), Just (Just v)) (Just m)) = Just (M.insert k v m) psi ([], []) = Nil psi (k:ks, []) = Cons (Just k, Nothing) (ks, []) psi ([], v:vs) = Cons (Nothing, Just v) ([], vs) psi (k:ks,v:vs) = Cons (Just k, Just v) (ks,vs)