9

Just [1]go fromとJust [2]toである、Haskell で盲目的に明白でなければならないことを実行しようとしていJust [1, 2]ます。しかし、関連しているが役に立たないページを見つけ続けているため、オンラインで何も見つけることができません。それで、どうやってこれを達成しますか?

4

4 に答える 4

16

使用できますliftA2 (++)

liftA2 (++) :: Maybe [a] -> Maybe [a] -> Maybe [a]

liftA2二項関数を にリフトするだけApplicativeです。Applicatives は、コンテキスト内の任意の引数の関数を持ち上げるために設計されているため、これには最適です。この場合、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 bfmap( 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 <*> xMaybe

したがって、 の定義を拡張できます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 、およびが既に変数であると記述して直接使用する方がより慣用的かもしれません。(一方、それを部分的に適用している場合、たとえば、高階関数に渡す場合は、望ましいです。)ApplicativeliftA2(++) <$> a <*> babliftA2 (++)

すべてMonadは であるApplicativeため、関数をコンテキストに「リフト」しようとしていることに気付いApplicativeた場合は、おそらく探しているものです。

于 2012-01-24T18:36:33.417 に答える
3

ソリューションを のリストに展開するにはJust、次を使用できます

fmap join $ sequence [Just[1],Just[2],Just[3]]
-- Just [1,2,3]
于 2012-01-24T21:19:10.537 に答える
3

@ehirdの答えは素晴らしいですが、私は次のような初心者向けのソリューションを使用したでしょう:

mergeJust a b = do
    a' <- a
    b' <- b
    return (a' ++ b')
于 2012-01-24T19:22:54.450 に答える
1

他のソリューションでは言及されていなかったので、ここで述べます。私の意見では、タスクを達成する最も簡単な方法は、<>(または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
于 2012-08-11T20:17:26.093 に答える