2017-02-18 3 views
0
Кроме

меня такая ситуация:Выписка из

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 

?

+0

Что будет использоваться для «пустого» корпуса? Вы должны передать его каким-то образом, либо явным параметром, либо словарем типа. – chi

+0

пустые случаи только там, чтобы «заполнить» либо. – Randomize

ответ

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) 
+0

Я не знал о Data.Default :) спасибо! – Randomize

3

Поскольку Except e является экземпляром Foldable, вы можете определить 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 s). Но идея в том, что mempty будет вашим значением по умолчанию; поскольку Except e m содержит либо ноль, либо один m s, fold будет включать значение по умолчанию, если оно пустое.

+0

Спасибо, это очень интересно. В настоящий момент типы не предназначены для «суммирования» (возможно, в будущем), но мне очень нравится идея. – Randomize

Смежные вопросы