2014-08-28 2 views
0

Вслед за this я следующие классы типов:Автоматически выводить многопараметрической экземпляр

class Monoid m => BuilderS m a where 
    cstr :: String -> a -> m 

class SafeCopy a where 
    putSafe :: a -> m 

Предоставление экземпляры для BuilderS:

import qualified Data.Serialize.Builder as B 

instance Serialize a => BuilderS B.Builder a where 
    cstr _ = B.fromByteString . encode 

instance BuilderS CustomBuilder Int where 
    cstr = ... 

instance BuilderS CustomBuilder String where 
    cstr = ... 

etc. 

Я хотел бы определить экземпляры SafeCopy как это:

data Person = Person { name :: String, age :: Int } 

instance SafeCopy Person where 
    putSafe p = cstr "name" (name p) 

Однако в этом конкретном ic компилятор не может найти экземпляр BuilderS m String. Я попробовал несколько вещей:

  • Добавить все примитивные типы данных с ограничениями putSafe: putSafe :: (BuilderS m Int, BuilderS m String, ...) => a -> m. Это работает, но не является расширяемым (то есть, если я хочу иметь ограничение BuilderS m Vector в будущем?)
  • Добавить m в параметры типа SafeCopy.
  • Используйте нестандартную сумму: data SumT m = forall a b. (BuilderS m a, BuilderS m b) => a :+: b, а затем получите putSafe :: a -> SumT m.

Тем не менее, я не располагаю достаточной информацией для системы типов, чтобы отложить решение о том, какой именно экземпляр BuilderS использовать для дальнейшего использования. Что мне не хватает?

+0

В чем была проблема с (2) [добавить m для ввода параметров]? – bennofs

+0

'm' из обоих случаев являются независимыми. Во втором случае 'm' является свободным параметром. Итак, вы должны написать вручную конечный тип, 'putSafe p = cstr" name "(name p) :: CustomBuilder String' – viorior

+2

Ваш тип для' putSafe' обещает быть в состоянии вернуть любой тип, который хочет сделать абонент. Ясно, что это невозможно. – augustss

ответ

1

Вы можете сделать что-то вроде этого:

class SafeCopy a m where 
    putSafe :: a -> m 

instance BuilderS m String => SafeCopy Person m where 
    putSafe p = cstr "name" (name p) 

Вам нужно включить много расширений языка.

+0

Отлично, спасибо. –

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