这是一个可怕的人为例子,但无论如何......这个样子:
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
并且工作
GHCI>让foo0 = foo(条形码)(\ n - > [n,n * 2])
GHCI> map(runFoo $ runBar foo0 4)[1..10]
[FALSE,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,FALSE]
但如果我将明显的类型签名添加到本地函数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
,如果在可比较的真实单词问题中出现了什么变通方法呢?
答案 0 :(得分:8)
显然您忘记将类型变量c
带入显式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
的变量才会进入范围。