在 Haskell 中,如何显式地给这个带有继承参数的特定集合函数签名?
In Haskell, how to explictly give a signature to this particular subfunction with inherited parameters?
假设你有这个功能
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
在loop
的主体中,i
被隐式定义为f
的参数。
但是,我在给 loop
签名时遇到了问题。他告诉我它应该是 ST s ()
,所以我在 loop
的定义上面写了 loop :: ST s ()
。
但是 ghc 抱怨它无法将 loop
中的 s
与 f
中的 s
相匹配。由于 loop
没有参数,它会在该循环的定义中创建自己的本地 forall s.
,从而防止与 f
的 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
假设你有这个功能
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
在loop
的主体中,i
被隐式定义为f
的参数。
但是,我在给 loop
签名时遇到了问题。他告诉我它应该是 ST s ()
,所以我在 loop
的定义上面写了 loop :: ST s ()
。
但是 ghc 抱怨它无法将 loop
中的 s
与 f
中的 s
相匹配。由于 loop
没有参数,它会在该循环的定义中创建自己的本地 forall s.
,从而防止与 f
的 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