gpt4 book ai didi

haskell - ScopedTypeVariables 无法与嵌套的 where 子句一起使用?

转载 作者:行者123 更新时间:2023-12-03 12:28:34 26 4
gpt4 key购买 nike

这是一个非常人为的例子,但无论如何......这个类型检查:

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> let foo0 = foo (Bar id) (\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 s,如果这出现在可比较的实际问题中,有什么解决方法?

最佳答案

显然你忘记带类型变量 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被纳入范围。

关于haskell - ScopedTypeVariables 无法与嵌套的 where 子句一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12176037/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com