从Except中提取

时间:2017-02-18 10:13:01

标签: haskell

我遇到这种情况:

import Control.Monad.Except

data Foo = Foo { i :: Int }
data Bar = Bar { i :: Int , v: Char }

emptyFoo = Foo 0
emptyBar = Bar 0 'N'

extractF :: (Except String Foo) -> Foo
extractF ex = either (const emptyFoo) id (runExcept ex)

extractB :: (Except String Bar) -> Bar
extractB ex = either (const emptyBar) id (runExcept ex)

有没有办法将上面的extract函数概括为一个,如:

myfoo = extract someFooInstanceWrappedInException
mybar = extract someBarInstanceWrappedInException

2 个答案:

答案 0 :(得分:3)

您可以声明一个提供默认值的类

-- Note: consider using Data.Default instead of creating your own class.
class Default a where
    def :: a

instance Default Foo where
    def = Foo 0

instance Default Bar where
    def = Bar 0 'N'

extract :: Default a => Except String a -> a
extract ex = either (const def) id (runExcept ex)

答案 1 :(得分:3)

由于Except eFoldable的实例,您可以为您的类型定义Monoid个实例并使用fold :: (Foldable f, Monoid m) => f m -> m

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Data.Monoid

newtype Foo = Foo { getFoo :: Sum Int } deriving Monoid

extractFoo :: Except e Foo -> Foo
extractFoo = fold

我完全不知道你的类型是什么意思,所以我只是用Sum给出了一个例子。 Monoid实例的正确语义将是特定于域的(并且您的类型甚至可能不是有效的Monoid)。但是这个想法是mempty将是你的默认值;由于Except e m包含零个或m个,fold会插入默认值(如果它为空)。