У меня есть модуль Data.FastSet, где определен этот класс типов:отказ в проверке типов кода с помощью Тип Families
{-# LANGUAGE TypeFamilies #-}
class HasFastSet elt where
type FastSet elt :: *
empty :: FastSet elt
fromList :: [elt] -> FastSet elt
member :: elt -> FastSet elt -> Bool
eq :: FastSet elt -> FastSet elt -> Bool
insert :: elt -> FastSet elt -> FastSet elt
union :: FastSet elt -> FastSet elt -> FastSet elt
filter :: (elt -> Bool) -> FastSet elt -> FastSet elt
вместе с несколькими экземплярами. Тогда, в каком-то другом модуле, я пытаюсь использовать:
{-# LANGUAGE RankNTypes, TypeFamilies, ScopedTypeVariables #-}
import qualified Data.FastSet as FS
data StaticInfo elt = StaticInfo { matchesEmpty :: Bool,
starters :: FS.FastSet elt }
sequentialCompose :: forall m elt. (Monad m, FS.HasFastSet elt) =>
m (StaticInfo elt) -> m (StaticInfo elt) -> m (StaticInfo elt)
sequentialCompose si1 si2 = do
StaticInfo me1 st1 <- si1
case me1 of
False -> si1
True -> do
StaticInfo me2 st2 <- si2
let together = FS.union st1 st2 :: FS.FastSet elt
return (StaticInfo me2 together)
Как вы видите, я пытался использовать расширение ScopedTypeVariables сказать, что программа проверки результате объединения двух множеств имеет тот же тип, что и наборы самих себя. Когда я пытаюсь скомпилировать это, он дает мне ошибку типа (и это то же самое, независимо от моей попытки дать явный тип для together
переменной:
Couldn't match expected type ‘FS.FastSet elt’
with actual type ‘FS.FastSet elt1’
NB: ‘FS.FastSet’ is a type function, and may not be injective
The type variable ‘elt1’ is ambiguous
Relevant bindings include
together :: FS.FastSet elt
(bound at /home/olympia/concurrency-talk/chat-benchmark/src/Text/Parsing/StaticInfo.hs:24:20)
st2 :: FS.FastSet elt
(bound at /home/olympia/concurrency-talk/chat-benchmark/src/Text/Parsing/StaticInfo.hs:23:31)
st1 :: FS.FastSet elt
(bound at /home/olympia/concurrency-talk/chat-benchmark/src/Text/Parsing/StaticInfo.hs:19:18)
si2 :: m (StaticInfo elt)
(bound at /home/olympia/concurrency-talk/chat-benchmark/src/Text/Parsing/StaticInfo.hs:18:23)
si1 :: m (StaticInfo elt)
(bound at /home/olympia/concurrency-talk/chat-benchmark/src/Text/Parsing/StaticInfo.hs:18:19)
sequentialCompose :: m (StaticInfo elt)
-> m (StaticInfo elt) -> m (StaticInfo elt)
(bound at /home/olympia/concurrency-talk/chat-benchmark/src/Text/Parsing/StaticInfo.hs:18:1)
In the expression: FS.union st1 st2 :: FS.FastSet elt
In an equation for ‘together’:
together = FS.union st1 st2 :: FS.FastSet elt
Что я делаю неправильно
проблема заключается в том, что 'elt -> FS.FastSet elt' не является * инъективным * (это означает, что могут быть' elt' и 'elt'' с тем же' FS.FastSet elt ~ FS.FastSet elt'' - сейчас вы не можете много сделать, но инъекционные типы-семьи уже в пути;) – Carsten
Я * думаю * вы можете придумать что-то, работая, если вы измените свои операции на 'union :: elt -> elt -> elt' вместо – Carsten
Я подозреваю, что 'FastSet' лучше должен быть ассоциированным семейством' data', а не типом семейства. Они являются инъективными. – leftaroundabout