问题描述
这是一个非常人为的例子,但是无论如何……这种类型的检查:
It's a horribly contrived example, but anyway... this typechecks:
newtype Foo c = Foo { runFoo :: c -> Bool }
newtype Bar c = Bar { runBar :: Int -> c }
foo :: Eq c => Bar c -> (c -> [c]) -> Bar (Foo c)
foo bar f = Bar res
where res n = Foo judge
where judge c = (c`elem`) . f $ runBar bar n
工作
但是如果我将明显的类型签名添加到本地函数 judge
,
but if I add the obvious type signature to the local function judge
,
foo :: Eq c => Bar c -> (c -> [c]) -> Bar (Foo c)
foo bar f = Bar res
where res n = Foo judge
where judge :: c -> Bool
judge c = (c`elem`) . f $ runBar bar n
失败
Could not deduce (c ~ c2)
from the context (Eq c)
bound by the type signature for
foo :: Eq c => Bar c -> (c -> [c]) -> Bar (Foo c)
,依此类推.在Haskell 98中不足为奇,但我认为 ScopedTypeVariables
应该允许编写此类签名,但显然不允许这样做.是否有特定的原因,是否有意使它不适用于嵌套的 where
,并且如果出现类似的实词问题,有什么解决方法?
and so on. Hardly surprising in Haskell 98, but I'd think ScopedTypeVariables
should allow to write such signatures, but apparently it doesn't. Is there a specific reason for this, is it intentional that it doesn't work with nested where
s, and what workarounds are there if this turns up in a comparable real-word problem?
推荐答案
显然,您忘记了将类型变量 c
引入显式的 forall
范围内,
Apparently you forgot to bring the type variable c
into scope with an explicit forall
,
{-# LANGUAGE ScopedTypeVariables #-}
module Foobar where
newtype Foo c = Foo { runFoo :: c -> Bool }
newtype Bar c = Bar { runBar :: Int -> c }
foo :: forall c. Eq c => Bar c -> (c -> [c]) -> Bar (Foo c)
foo bar f = Bar res
where res n = Foo judge
where judge :: c -> Bool
judge c = (c`elem`) . f $ runBar bar n
编译良好.
ScopedTypeVariables
本身不会将签名中的类型变量带入范围,仅将具有显式 forall
的那些变量带入范围.
ScopedTypeVariables
by itself doesn't bring the type variables from the signature into scope, only those with an explicit forall
are brought into scope.
这篇关于ScopedTypeVariables无法与嵌套where子句一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!