Я хотел бы выразить тип данных с полем sType, чтобы он был чем-то, что является экземпляром SType (из zeromq-haskell).
Есть некоторая двусмысленность в том, что вы подразумеваете здесь под "чем-нибудь".
Хотите ли вы просто создать SocketOpts
значения с параметрическим типом и применить требование для экземпляра SType
, когда используется значение SocketOpts
? Тогда нормальный параметризованный тип подходит, как при редактировании.
Хотите ли вы, чтобы любое значение SocketOpts
имело экземпляр для указанного типа, применяя ограничение при создании, а не использовании значения? Тогда будет работать определение GADT:
data SocketOpts st where
SocketOpts :: (SType st) => SocketEnd -> st -> SocketOpts st
Хотите ли вы использовать какой-либо экземпляр для создания SocketOpts
значения, без параметризации его конкретным типом? Это экзистенциальный тип будет работать:
data SocketOpts where
SocketOpts :: (SType st) => SocketEnd -> st -> SocketOpts
... но имейте в виду, что экзистенциалы могут быть неуклюжими, и что все, что вы можете сделать с чем-то вроде этого, это сопоставление с шаблоном в SocketOpts
, а затем использовать методы, определенные для SType
. Знание определенного типа теряется.
Или, наконец, вы хотите выбрать какой-либо экземпляр, когда с использованием значения a SocketOpts
, отказавшись от возможности создать экземпляр определенного типа? Это универсально выраженный тип:
data SocketOpts where
SocketOpts :: SocketEnd -> (forall st. SType st => st) -> SocketOpts
... я верю, что это была ваша оригинальная версия. В этом случае вы не можете использовать мономорфное значение для создания значения SocketOpts
, только полиморфное значение - подумайте о разнице между значением Int
11 и числовым литералом 11 :: Num a => a
. Имейте в виду, что в этом случае GHC все еще нужно знать, какой экземпляр выбрать, поэтому при использовании содержимого SocketOpts
вам потребуется определенный тип перед использованием любых методов SType
.
Обе ошибки, которые вы видели, произошли из приведенных выше предупреждений об универсально квантифицированных типах: «неоднозначный тип», потому что вы применили что-то, что нужно для выбора экземпляра SType
, не предоставив GHC достаточно информации для этого, и «не смог вывести "ошибку, потому что вы пытались создать SocketOpts
с мономорфным значением.
Я подозреваю, что экзистенциальная версия - это то, что вы пытались найти. Однако, если у вас нет веских причин смешивать разные экземпляры SType
, параметрический GADT, вероятно, является лучшим выбором.