По-видимому, несколько рассеянно я написал что-то вроде:
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
class Foo f where
type Bar f :: *
retbar :: Bar f -> IO f
type Baz f = (Foo f, Eq f)
-- WithBar :: * -> (*->Constraint) -> * -> Constraint
type WithBar b c f = (c f, Bar f ~ b)
instance Foo () where
type Bar () = ()
retbar = return
naim :: WithBar () Baz u => IO u -- why can I do this?
naim = retbar ()
main = naim :: IO ()
Только после успешной компиляции я понял, что это не должно на самом деле работать: Baz
определяется как синоним типа с одним аргументом, но здесь я использую его без прямого аргумента. Обычно GHC лает на меня Type synonym ‘Baz’ should have 1 argument, but has been given none
, когда я пытаюсь сделать что-то подобное.
Теперь не поймите меня неправильно: мне бы очень хотелось написать это, и достаточно легко увидеть, как это может работать в этом конкретном примере (простое встраивание WithBar
даст подпись naim :: (Foo u, Bar u ~ ()) => IO u
, что, безусловно, хорошо), но что я не понимаю, почему это на самом деле работает именно так здесь. Возможно, это только ошибка в ghc-7.8.2
, позволяющая это сделать?