首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell Applicative和ErrorT?

Haskell Applicative和ErrorT?
EN

Stack Overflow用户
提问于 2010-03-20 14:02:00
回答 2查看 303关注 0票数 0

为什么我可以做到以下几点:

代码语言:javascript
复制
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

但我不能这样做:

代码语言:javascript
复制
f2 = (+) <$> getW1 <*> getW1

我该如何修改f2,让它按我想要的那样工作?

EN

回答 2

Stack Overflow用户

发布于 2010-03-20 14:59:44

<$>只要求该ErrorT String GetFunctor的一个实例。<*>要求它是Applicative的一个实例。我认为这个实例声明应该是有效的:

代码语言:javascript
复制
{-# LANGUAGE FlexibleInstances #-}

instance (Error e, Monad m) => Applicative (ErrorT e m) where
    pure = return
    (<*>) = ap
票数 3
EN

Stack Overflow用户

发布于 2013-01-16 01:19:40

要进行错误处理,您不需要Either(T) monad。你可以通过组合保持在Applicative中,这是非常好的。示例(有趣的是使用AccValidation,它会累积所有错误):

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2482136

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档