Косвенно ссылаться на конкретные и неспецифические объекты в Haskell без монад - PullRequest
2 голосов
/ 11 июля 2019

Я хочу хранить набор элементов разных «сортов» в структуре данных контейнера (list, set, ..) и косвенно ссылаться на них откуда-то еще.Обычно вы, вероятно, использовали бы тип суммы для элементов и, возможно, список в качестве контейнера или подобного:

data Element = Sort1 | Sort2 String | ...
type ElementList = List Element

Теперь я хочу использовать (и сохранить) какие-то ссылки на элементы списка (например, используя индекс для его позиции в списке - давайте пока представим, что список не меняется и, таким образом, это хорошая идея).Я хочу иметь возможность ссылаться на элементы, где меня не волнует «сортировка» И вот в чем загвоздка: я также хочу иметь возможность ссылаться на элементы и сообщать в типе, что это из какого-то определенногоСортировать.Это исключает простое решение типа суммы выше (потому что сортировка не в типе!).Я попробовал решение с GADTs:

{-#LANGUAGE GADTs, EmptyDataDecls, RankNTypes, ScopedTypeVariables #-}
data Sort1
data Sort2

data Element t where
  Sort1Element :: Element Sort1
  Sort2Element :: String -> Element Sort2

newtype ElementRef a = ElementRef Int

type UnspecificElementRefs = [forall t. ElementRef (Element t)]
type OneSpecificSort1ElementRef = ElementRef (Element Sort1)

main = do
  let unspecificElementRefs :: UnspecificElementRefs = [ElementRef 1, ElementRef 2]
  let oneSpecificElementRef :: OneSpecificSort1ElementRef = ElementRef 1
  putStrLn "hello"

Но это дает мне ошибку: - Недопустимый полиморфный тип: forall t.ElementRef (Element t) - GHC еще не поддерживает непредсказуемый полиморфизм - В объявлении синонима типа для 'UnspecificElementRefs'

   |
11 | type UnspecificElementRefs = [forall t. ElementRef (Element t)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Как я могу решить эту проблему?Я не ищу решение этой конкретной ошибки (я полагаю, это тупик?) Или конкретно с помощью GADT, или даже с использованием индекса int для ссылок или около того, я просто хочу решение, которое:

  • решает основную проблему косвенной ссылки на что-то неспецифичное, а также на что-то конкретное
  • не использует STRef или подобное, так что вся моя программа должна быть монадой (поскольку это довольно центральная структура данных)

1 Ответ

4 голосов
/ 11 июля 2019

«Предиктивный полиморфизм» означает, что у вас есть ∀, заключенный в конструктор типов, отличный от ->. В этом случае в []. Как говорится в сообщении об ошибке, GHC Haskell не поддерживает это (не то, чтобы это не было в принципе разумно, но, насколько я понимаю, проверка типов становится настоящим кошмаром).

Эту проблему можно решить, обернув ∀ во что-то, что образует «барьер проверки типа»: в новом типе.

newtype UnspecificElementRef = UnspecificElementRef (∀ t. ElementRef (Element t))
type UnspecificElementRefs = [UnspecificElementRef]

На самом деле это можно упростить, поскольку ElementRef сам по себе является оберткой нового типа с аргументом фантомного типа:

newtype UnspecificElementRef = UnspecificElementRef Int
...