Экзистенциальная квантификация ограничений класса типов

Я не уверен, почему ko не проверяет тип. Есть ли особенно поучительное объяснение?

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE NoMonomorphismRestriction, FlexibleInstances #-}

module Wrap where

class ExpSYM repr where
    lit :: Int -> repr

newtype Wrapped = Wrapped{unWrap :: forall repr. ExpSYM repr => repr}

a = (lit <$> Just 5) :: ExpSYM expr => Maybe expr

ko :: Maybe Wrapped
ko = do v <- a
        return $ Wrapped $ v

ok :: Maybe Wrapped
ok = do v <- Just 5
        let e = lit v
        return $ Wrapped $ e

Компилятор упоминает

SO.hs:15:14: error:
    • No instance for (ExpSYM a0) arising from a use of ‘a’
    • In a stmt of a 'do' block: v <- a
      In the expression:
        do { v <- a;
             return $ Wrapped $ v }
      In an equation for ‘ko’:
          ko
            = do { v <- a;
                   return $ Wrapped $ v }

SO.hs:16:28: error:
    • Couldn't match expected type ‘repr’ with actual type ‘a0’
        because type variable ‘repr’ would escape its scope
      This (rigid, skolem) type variable is bound by
        a type expected by the context:
          ExpSYM repr => repr
        at SO.hs:16:18-28
    • In the second argument of ‘($)’, namely ‘v’
      In the second argument of ‘($)’, namely ‘Wrapped $ v’
      In a stmt of a 'do' block: return $ Wrapped $ v
    • Relevant bindings include v :: a0 (bound at SO.hs:15:9)
Failed, modules loaded: none.

Редактировать: Нашел хорошее решение, чтобы обойти это в примечании Олега, которое состоит в том, чтобы специализировать тип таким образом, чтобы полиморфизм удалялся приложением типа, добавляя экземпляр

instance ExpSYM Wrapped where
   lit x = Wrapped $ lit x

тогда у нас есть

notko :: Maybe Wrapped
notko = do v <- a    
           return $ v -- note the difference. what's the type of a ?

-- and we get all the usual goodies, no silly impredicative error
alsoOk = lit <$> Just 5 :: Maybe Wrapped

person nicolas    schedule 07.11.2017    source источник
comment
Что вы имеете в виду под не работает. Укажите ошибку компиляции/неожиданный вывод и т. д.   -  person Willem Van Onsem    schedule 07.11.2017
comment
Я имел в виду typecheck, конечно. все знают, что после проверки типов все работает ;) - (хотя вы правы)   -  person nicolas    schedule 07.11.2017
comment
Ошибка говорит о том, что с newtype уже что-то не так, а не с ko/ok.   -  person Willem Van Onsem    schedule 07.11.2017


Ответы (1)


ko будет работать, только если тип a будет

a :: Maybe (∀ expr . ExpSYM expr => expr)
a = lit <$> Just 5

... потому что только тогда вы сможете развернуть его, чтобы получить полиморфное значение v :: ∀ expr . ExpSYM expr => expr. Это значение должно быть полиморфным, чтобы его можно было использовать в Wrapped.

Но Maybe (∀ expr . ExpSYM expr => expr) является непредикативным типом. GHC Haskell не поддерживает непредикативные типы.

OTOH, в ok v - это просто скучное старое целое число, происходящее от не впечатляющего Just 5 :: Maybe Int. Только e вводит полиморфизм, но вне монады Maybe.

person leftaroundabout    schedule 07.11.2017
comment
на месте. благодарю вас. поэтому полиморфизм должен быть последним. У меня есть еще один очень противоречивый пример, когда переключение с последовательных приложений g на f, примененное к некоторому значению, работает, в то время как сначала составить функции и применить их к значению не удается. немного смущает.. - person nicolas; 07.11.2017