0

なぜ私は次のことができるのですか:

import Data.Word
import Data.Binary.Get
import Control.Applicative
import Control.Monad.Error

getW1 :: ErrorT String Get Word8
getW1 = lift getWord8

f1 = (+1) <$> getW1

しかし、私はできません:

f2 = (+) <$> getW1 <*> getW1

また、意図したとおりに機能するように f2 を変更するにはどうすればよいですか?

4

2 に答える 2

3

<$>ErrorT String Getのインスタンスである必要があるだけですFunctor<*>のインスタンスである必要がありますApplicative。このインスタンス宣言はうまくいくはずだと思います:

{-# LANGUAGE FlexibleInstances #-}

instance (Error e, Monad m) => Applicative (ErrorT e m) where
    pure = return
    (<*>) = ap
于 2010-03-20T06:59:43.620 に答える
0

Either(T)エラー処理を行うために、モナドは必要ありません。Applicativeあなたは作曲を介してとどまることによって完全に元気になることができます。AccValidation例(すべてのエラーを蓄積する楽しみのために):

import Control.Applicative
import Control.Monad.Error

import Data.Validation
import Data.Bifoldable
import Data.Functor.Compose

-- Replicating OP example with a Dummy monad (Get is made Applicative in newer libs)

data Dummy a = D a
  deriving Show

instance Monad Dummy where
  return = D
  (D x) >>= f = f x

instance Functor Dummy where
  fmap f (D x) = D (f x)

getM1 :: ErrorT String Dummy Int
getM1 = lift (D 1)

-- Can do with Applicatives + (Acc)Validation too

instance Applicative Dummy where
  pure = return
  (<*>) = ap

getA :: Compose Dummy (AccValidation String) Int
getA = Compose $ D (success 1)

getE :: Compose Dummy (AccValidation String) Int
getE = Compose $ D (failure "bad")

-- Applicative composition can work either way

getA2 :: Compose (AccValidation String) Dummy Int
getA2 = Compose $ success (D 1)

getE2 :: Compose (AccValidation String) Dummy Int
getE2 = Compose $ failure "bad"

main = do
    runMonadic $ (+) <$> getM1 <*> getM1    -- D "2"
    --
    runApplicative $ (+) <$> getA  <*> getA   -- D "2"
    runApplicative $ (+) <$> getE  <*> getA   -- D "bad"
    runApplicative $ (+) <$> getE  <*> getE   -- D "badbad"
    --
    runOtherApp    $ (+) <$> getA2 <*> getA2  -- "D 2"
    runOtherApp    $ (+) <$> getE2 <*> getE2  -- "badbad"
    where
      runMonadic      = print . fmap (either id show) . runErrorT
      runApplicative  = print . fmap (validate id show) . getCompose
      runOtherApp     = print . validate id show . getCompose

-- some helper mimicking @either@ of @Either@
validate :: (e -> c) -> (a -> c) -> AccValidation e a -> c
validate f g = bifoldl (const f) (const g) undefined
于 2013-01-15T17:19:40.053 に答える