2016-09-30 2 views
5

Предположим, что у меня полиморфный тип, где один из параметров - более высокий тип (* -> *).Производятся с переменными типа более высокого типа

data Tricky m = Tricky { numbers :: m Int, genesis :: m String } 

Существует ли общий способ получения экземпляров для таких типов без использования тайных и небезопасных языковых расширений?

Я пытался позволяет StandaloneDeriving, так что я мог бы указать контекст:

deriving instance Show (m Int) => Show (Tricky m) 

Но GHC затем жалуется на ограничение не будучи не меньше, чем голова экземпляра, и указывает мне в направлении UndecidableInstances.

Резюмируя:

1. Должен ли я просто идти вместе с этим советом, или есть способ лучше?

2. Есть ли какие-либо предложения, чтобы облегчить этот процесс?

3. Как-то нехорошо хотеть выводить «высшие» экземпляры? Было бы лучше, чтобы получить экземпляры для нескольких конкретных типов вместо (например. Vector, [], Set)

ответ

8

1. Там нет ничего небезопасного о UndecidableInstances.

Существует еще один способ определения Show (Tricky m), который требует, чтобы m удовлетворяет forall a. Show a => Show (m a). Это захвачено как

класса типов
class Show1 f where 
    showsPrec1 :: Show a => Int -> f a -> ShowS 

even cleverer version of Show1 было добавлено в базу 4.9. Это более общее, поскольку он может использоваться для отображения m a, когда a не имеет экземпляра Show a.

2. Вы нашли правильные кусочки для этого.

3. Нет, это правильно возглавляемые абстрагироваться над еще более высоким kinded структур как Vector[], и Set. Трансформаторы Monad имеют вид (* -> *) -> (* -> *) и абстрактные типы типов (* -> *), такие же, как функтор, для создания типов с тем же видом, что и функтор. Tricky имеет вид (* -> *) -> *, он принимает что-то с тем же видом, что и функтор, и производит обычный тип данных. Я называю типы данных такого типа «Модели», так как они создают абстрагирование типа данных по тому, как он объединяется.

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