8

タイプの2つの値とがt1あります。-valueは、エラー処理に使用されます。これらの値は、を返す関数で使用されます。t2Either String TypeLeftEither String Type

私がやりたいのは、とが両方とも-valuesであり、を満たすかどうかを確認t1するt2ことRightですp :: Type -> Bool。もしそうなら、私は戻りたいですRight (the type inside t1)t1とが両方ともt2-valuesRightであるが、を満たさない場合はp、を返しLeft someStringます。またはが値のt1場合t2Leftその値を渡したいだけです。

どうすればエレガントな方法でこれを行うことができますか?どちらかをモナドとして使用するのが正しいことだと思いますが、どうすればよいかわかりません。

4

4 に答える 4

12

なぜモナド?

test p (Right t1) (Right t2) | p t1 && p t2 = Right t1
                             | otherwise = Left "nope"
test _ (Left t1) _ = Left t1
test _ _ (Left t2) = Left t2
于 2011-06-09T09:39:24.610 に答える
5

でそれを実行したい場合は、Monad次のようになりますが、のMonadインスタンスEitherが最近変更されたため、最近のGHCでは実際には機能しません。

do v1 <- t1
   v2 <- t2
   guard (p v1 && p v2) `mplus` Left someString
   return v1
于 2011-06-09T09:30:29.050 に答える
4

独自のErrorデータ型を作成し、それをMonadのインスタンスにすることができます。

data Computation a = Error String | Result a


instance Monad Computation where
    (Result x)  >>= k   =  k x
  e@(Error a)   >>= k   =  e

次に、 GaneshSittampalamによって説明されている方法を使用します。(インスタンスMonadPlusComputationも追加する必要があります。

完全を期すために更新すると、次のようになります。

import Control.Monad

data Computation a = Error String | Result a



instance Monad Computation where
  return a = Result a
  (Result x)  >>= k   =  k x
  (Error a)   >>= k   =  Error a

instance MonadPlus Computation where
  mzero              = Error "Always fail"
  mplus (Error a) r  = r
  mplus l         _  = l


check :: (Int -> Bool) -> Computation Int  
check p =   do v1 <- Result 4
               v2 <- Result 2
               guard (p v1 && p v2) `mplus` Error "someString"
               return v1
于 2011-06-09T10:49:48.113 に答える
1

Left本当に必要な場合は、値の伝播からモナディックアクションを分離できます。

import Control.Monad
import Control.Applicative
import Control.Monad.Instances

これにより、単純なモナディックアクションが生成されます。

foo :: Type -> Type -> Either String Type
foo t1 t2 | p t1 && p t2 = Right t1
          | otherwise    = Left somestring

これをモナディック引数に適用して、必要な関数を取得できます。

fooM :: Either String Type -> Either String Type -> Either String Type
fooM t1 t2 = join (foo <$> t1 <*> t2)

または同等に

fooM t1 t2 = do
    a <- t1
    b <- t2
    foo a b
于 2011-06-09T20:11:00.543 に答える