Как Вы соответствуете против типа “Любому b”?

Цель для этой конкретной части кода состоит в том, чтобы сделать size функция, более эффективная, чем простое включение всех элементов elems. Я обосновался на подведении итогов двух типов, которые составляют список, но я, может казаться, не создаю подпись функции размера.

instance (Finite a, Finite b) => Finite (Either a b) where
    elems = combineLists [Left x | x <- elems] [Right x | x <-elems]
    size ??? = (size a) + (size b)

Из Вводной части мы знаем это Either a b = Left a | Right b.

Первая вещь, которую я попробовал, состояла в том, чтобы соответствовать Either, но конечно это - тип, так, чтобы не работал. Затем, я попробовал ((Left a) | (Right b)), но не пойдите на это также. Ничто иное, кажется, не соответствует типу Either a b.

Я смог добраться size (Left a) скомпилировать, но так как это отсутствует b компонент, я получаю ошибку:

Ambiguous type variable `b' in the constraint:
  `Finite b' arising from a use of `size' at <interactive>:1:0-12

который, конечно, имеет смысл в контексте, но у меня действительно нет подсказки, как соответствовать Either a b.

У кого-либо есть какие-либо мысли?

12
задан nbro 9 September 2017 в 23:50
поделиться

3 ответа

Что-то типа Either a b является либо Left a, либо Right b, поэтому у вас есть два случая, которые можно обрабатывать отдельно:

size (Left x) = size x
size (Right x) = size x

Ошибка о неоднозначной переменной типа - это отдельная проблема. Если вы просто вводите в интерпретатор что-то вроде size (Left 1), система не может определить "правильный" тип этого Left 1 значения. Это может быть Either Int anything и пока неизвестно, какого типа это anything - нельзя проверить, находится ли оно в классе Finite (что требуется size).

Вы можете избежать этой проблемы, указав явную сигнатуру типа:

size (Left 1 :: Either Int String)
25
ответ дан 2 December 2019 в 06:08
поделиться

Проблема, похоже, в том, что вам нужен фиктивный аргумент для size, но вы не можете передать фиктивные аргументы для обоих типов a и b в одном Either a b. Возможно, вы можете использовать elems для получения манекена каждого типа:

size _ = (size . head) (elems :: [a]) + (size . head) (elems :: [b])
0
ответ дан 2 December 2019 в 06:08
поделиться

Я думаю, что основная проблема, с которой вы столкнулись, заключается в том, что вам нужен тип, который одновременно представляет данные каждого из двух других типов. Либо a b может быть только одним из a или b в данный момент времени.

Простой тип данных, который представляет одновременно a и b , представляет собой кортеж из двух элементов. Сигнатура типа для такой вещи - (a, b) , которая также является выражением для ее создания и, следовательно, для обработки шаблона:

> :type (4,5)
(4,5) :: (Num t, Num t1) => (t, t1)
> let f (a, b) = 2*a + b
> f (4,5)
13

Вам следует подумать о том, чтобы написать свою первую строку с двумя кортежами , например:

 instance (Finite a, Finite b) => Finite (a, b) where

Что представляет собой Finite (a, b) ? Какими будут определения функций-членов?

0
ответ дан 2 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: