Цель для этой конкретной части кода состоит в том, чтобы сделать 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
.
У кого-либо есть какие-либо мысли?
Что-то типа 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)
Проблема, похоже, в том, что вам нужен фиктивный аргумент для size
, но вы не можете передать фиктивные аргументы для обоих типов a
и b
в одном Either a b
. Возможно, вы можете использовать elems
для получения манекена каждого типа:
size _ = (size . head) (elems :: [a]) + (size . head) (elems :: [b])
Я думаю, что основная проблема, с которой вы столкнулись, заключается в том, что вам нужен тип, который одновременно представляет данные каждого из двух других типов. Либо 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)
? Какими будут определения функций-членов?