类ST封装
ST-like encapsulation
我正在尝试使用类型系统来确保永远不会从 monad M 中取出 X。我希望它的工作方式类似于 runST
,其中不可能混合来自不同的线程。
data X s = X Int
type M s = State Int
newX :: M s (X s)
newX = X <$> get
eval :: (forall s. M s a) -> a
eval x = evalState x 0
但是下面的代码不会导致类型错误:
ghci> x = eval newX
ghci> :t x
x :: X s
为什么 ST monad 中的类似代码会抛出错误而我的却不会?根据我的理解,M s a
中的 s
应该绑定,使 X s
中的 s
成为自由类型变量,从而导致类型检查器出错。
要强制类型抽象,您必须使用 data
或 newtype
,而不是 type
。
type
同义词中未使用的参数根本没有作用:
type M s = State Int
所以这些是等价的:
newX :: M s (X s)
newX :: State Int (X s)
eval :: (forall s. M s a) -> a
eval :: State Int a -> a
eval
实际上并不是更高级别的。
我正在尝试使用类型系统来确保永远不会从 monad M 中取出 X。我希望它的工作方式类似于 runST
,其中不可能混合来自不同的线程。
data X s = X Int
type M s = State Int
newX :: M s (X s)
newX = X <$> get
eval :: (forall s. M s a) -> a
eval x = evalState x 0
但是下面的代码不会导致类型错误:
ghci> x = eval newX
ghci> :t x
x :: X s
为什么 ST monad 中的类似代码会抛出错误而我的却不会?根据我的理解,M s a
中的 s
应该绑定,使 X s
中的 s
成为自由类型变量,从而导致类型检查器出错。
要强制类型抽象,您必须使用 data
或 newtype
,而不是 type
。
type
同义词中未使用的参数根本没有作用:
type M s = State Int
所以这些是等价的:
newX :: M s (X s)
newX :: State Int (X s)
eval :: (forall s. M s a) -> a
eval :: State Int a -> a
eval
实际上并不是更高级别的。