说你有这个功能
import Control.Monad
import Control.Monad.ST
import Data.STRef
f :: (Num a, Ord a) => STRef s a -> ST s ()
f i = loop
where
loop = do
_i <- readSTRef i
writeSTRef i (_i - 1)
when (_i > 1) loop
Run Code Online (Sandbox Code Playgroud)
inloop的主体,i被隐式定义,因为它是来自 的参数f。但是我在给loop. Hie 告诉我它应该是ST s (),所以我写loop :: ST s ()了上面loop的定义。
但是 ghc 抱怨它无法将sfromloop与sfrom匹配f。由于loop没有参数,它forall s.在该循环的定义中创建了自己的局部变量,以防止与f's匹配s。
但令人惊讶的是,它在没有显式签名的情况下编译。PartialTypeSignature 有效,但它很丑陋,并且不允许引用s. 如果我只是将其添加i为参数,它也会编译,loop但假设我很懒。
如何loop以编译方式明确指定的签名?
用隐式类型编译的所有东西都可以被赋予显式类型以便它仍然编译,这是不是真的?
解决方案确实在于 -XScopedTypeVariables
问题来自这样一个事实,即如果您想引用一个已经存在的类型变量,则必须明确量化该变量。
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad
import Control.Monad.ST
import Data.STRef
f :: forall s a. (Num a, Ord a) => STRef s a -> ST s ()
f i = loop
where
loop :: ST s ()
loop = do
_i <- readSTRef i
writeSTRef i (_i - 1)
when (_i > 1) loop
Run Code Online (Sandbox Code Playgroud)