类型类约束的存在量化
Existential quantification of typeclass constraints
我不确定为什么 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.
编辑:
在 Oleg 的笔记中找到了一个很好的解决方案来规避这个问题,即专门化类型,以便通过类型应用程序删除多态性,添加实例
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
ko
只有在 a
的类型是
时才有效
a :: Maybe (∀ expr . ExpSYM expr => expr)
a = lit <$> Just 5
...因为只有这样你才能解包它以获得多态值v :: ∀ expr . ExpSYM expr => expr
。该值必须是多态的,因此它实际上可以在 Wrapped
.
中使用
但是 Maybe (∀ expr . ExpSYM expr => expr)
是一个 impredicative type。 GHC Haskell 不支持谓词类型。
OTOH,在 ok
中,v
只是一个无聊的旧整数,来自一个不起眼的 Just 5 :: Maybe Int
。只有 e
引入了多态性,但在 Maybe
monad 之外这样做。
我不确定为什么 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.
编辑: 在 Oleg 的笔记中找到了一个很好的解决方案来规避这个问题,即专门化类型,以便通过类型应用程序删除多态性,添加实例
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
ko
只有在 a
的类型是
a :: Maybe (∀ expr . ExpSYM expr => expr)
a = lit <$> Just 5
...因为只有这样你才能解包它以获得多态值v :: ∀ expr . ExpSYM expr => expr
。该值必须是多态的,因此它实际上可以在 Wrapped
.
但是 Maybe (∀ expr . ExpSYM expr => expr)
是一个 impredicative type。 GHC Haskell 不支持谓词类型。
OTOH,在 ok
中,v
只是一个无聊的旧整数,来自一个不起眼的 Just 5 :: Maybe Int
。只有 e
引入了多态性,但在 Maybe
monad 之外这样做。