Давайте попробуем еще более простой пример:
data Foo x = Bar
foobar :: Foo a -> Foo b
foobar f = f
Взгляните на определение Foo
. С левой стороны есть переменная типа (x
), которая на самом деле нигде не появляется справа. Это пример так называемой «переменной типа фантома». В сигнатуре типа есть тип, который на самом деле не соответствует типу чего-либо в фактическом значении. (И это совершенно законно, кстати.)
Теперь, если у вас есть выражение Just True
, то с True :: Bool
, тогда Just True :: Maybe True
. Однако выражение Nothing
определенно является Maybe
чем-то . Но при отсутствии фактического значения нет ничего, что могло бы заставить его быть каким-то конкретным типом возможных типов. Переменная типа в данном случае фантомная.
У нас здесь похожая вещь; Bar :: Foo x
, для любого x
. Так что вы бы подумали , что наше определение foobar
является законным.
И вы будете ошибаться .
Нельзя передать значение Foo a
, где ожидается значение типа Foo b
, , даже если имеют точно такую же структуру времени выполнения. Поскольку средство проверки типов не заботится о структуре времени выполнения; он заботится только о типах . Что касается проверки типов, Foo Int
отличается от Foo Bool
, хотя во время выполнения нет заметной разницы.
И , что является причиной отклонения вашего кода.
На самом деле, вы должны написать
foobar :: Foo a -> Foo b
foobar Bar = Bar
чтобы средство проверки типов знало, что выводимый вами Bar
является новым, отличным Bar
от того, который вы получили в качестве ввода (и, следовательно, он может иметь другой тип).
Верьте или нет, это на самом деле функция , а не ошибка. Вы можете написать код, который делает так, чтобы (например) Foo Int
вел себя не так, как Foo Char
. Хотя во время выполнения они оба просто Bar
.
Решение, как вы обнаружили, состоит в том, чтобы просто взять ваше значение b
из Right
, а затем немедленно вернуть его обратно. Это кажется бессмысленным и глупым, но это должно явно сигнализировать контролеру типов, что типы потенциально изменились. Возможно, это раздражает, но это только один из тех уголков языка. Это не ошибка, он специально разработан для такой работы.