Just [1]
go fromとJust [2]
toである、Haskell で盲目的に明白でなければならないことを実行しようとしていJust [1, 2]
ます。しかし、関連しているが役に立たないページを見つけ続けているため、オンラインで何も見つけることができません。それで、どうやってこれを達成しますか?
4 に答える
使用できますliftA2 (++)
:
liftA2 (++) :: Maybe [a] -> Maybe [a] -> Maybe [a]
liftA2
二項関数を にリフトするだけApplicative
です。Applicative
s は、コンテキスト内の任意の引数の関数を持ち上げるために設計されているため、これには最適です。この場合、Applicative
使用している は ですMaybe
。これがどのように機能するかを確認するには、定義を確認します。
liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b
(<$>)
純粋な値の関数を : 内で動作する関数に持ち上げるだけf
です(a -> b) -> f a -> f b
。fmap
( sに精通している場合は、の単なるエイリアスですFunctor
。) の場合Maybe
:
_ <$> Nothing = Nothing
f <$> Just x = Just (f x)
(<*>)
少しトリッキーです: : 内f
の値に関数を適用しf
ますf (a -> b) -> f a -> f b
。の場合Maybe
:
Just f <*> Just x = Just (f x)
_ <*> _ = Nothing
(実際、はのf <$> x
と同じものpure f <*> x
です。)Just f <*> x
Maybe
したがって、 の定義を拡張できますliftA2 (++)
。
liftA2 (++) a b = (++) <$> a <*> b
-- expand (<$>)
liftA2 (++) (Just xs) b = Just (xs ++) <*> b
liftA2 (++) _ _ = Nothing
-- expand (<*>)
liftA2 (++) (Just xs) (Just ys) = Just (xs ++ ys)
liftA2 (++) _ _ = Nothing
実際、これらの演算子を使用して、 のパターンに従うだけで、任意の数の引数の関数を任意の に持ち上げることができます。これはapplicative styleと呼ばれ、慣用的な Haskell コードでは非常に一般的です。この場合、 、 if 、およびが既に変数であると記述して直接使用する方がより慣用的かもしれません。(一方、それを部分的に適用している場合、たとえば、高階関数に渡す場合は、望ましいです。)Applicative
liftA2
(++) <$> a <*> b
a
b
liftA2 (++)
すべてMonad
は であるApplicative
ため、関数をコンテキストに「リフト」しようとしていることに気付いApplicative
た場合は、おそらく探しているものです。
ソリューションを のリストに展開するにはJust
、次を使用できます
fmap join $ sequence [Just[1],Just[2],Just[3]]
-- Just [1,2,3]
@ehirdの答えは素晴らしいですが、私は次のような初心者向けのソリューションを使用したでしょう:
mergeJust a b = do
a' <- a
b' <- b
return (a' ++ b')
他のソリューションでは言及されていなかったので、ここで述べます。私の意見では、タスクを達成する最も簡単な方法は、<>
(またはmappend
) fromを使用することData.Monoid
です。
import Data.Monoid
Just [1,2] <> Just [7,8] == Just [1,2,7,8]
ただし、このソリューションは、ehird の応用ソリューションとは異なり、値が短絡しないことに注意してくださいNothing
。
Just [1,2] <> Nothing ---> Just [1,2]
--However
(++) <$> Just [1,2] <*> Nothing ---> Nothing