Вслед за 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
использовать для дальнейшего использования. Что мне не хватает?
В чем была проблема с (2) [добавить m для ввода параметров]? – bennofs
'm' из обоих случаев являются независимыми. Во втором случае 'm' является свободным параметром. Итак, вы должны написать вручную конечный тип, 'putSafe p = cstr" name "(name p) :: CustomBuilder String' – viorior
Ваш тип для' putSafe' обещает быть в состоянии вернуть любой тип, который хочет сделать абонент. Ясно, что это невозможно. – augustss