让我们首先看一下web-gl包中的一个类似功能,其目的是这样的:
withShaders
:: forall bindings eff a
. Shaders ({ | bindings }) -> (String -> EffWebGL eff a) -> ({ webGLProgram :: WebGLProg | bindings } -> EffWebGL eff a) -> EffWebGL eff a
makeAff
:: forall e a
. ((Error -> Eff e Unit) -> (a -> Eff e Unit) -> Eff e Unit) -> Aff e a
withShadersAff :: forall eff a. Shaders { | a } -> Aff ( webgl ∷ WebGl | eff ) { webGLProgram ∷ WebGLProg | a }
withShadersAff arg = makeAff (\err ok -> withShaders arg (error >>> err) ok)
这基本上将基于回调的withShaders
函数转换为可以在aff
上下文中使用的函数。
我想知道为什么,以下功能(同样来自webgl包)不能使用同一功能:
runWebGL :: forall a eff. String -> (String -> Eff eff a) -> (WebGLContext -> EffWebGL eff a) -> Eff eff a
runWebGLAff :: forall eff . String -> Aff ( webgl ∷ WebGl | eff ) WebGLContext
runWebGLAff arg = makeAff (\err ok -> runWebGL arg (error >>> err) ok)
这给我最后一个函数的“无限类型错误”。我猜是因为错误回调和成功回调没有共享相同的结果类型,但是我找不到解决的办法。
编辑
阅读了正确的答案后,解决方法是:
runWebGLAff arg = makeAff (\err ok -> runWebGL arg (error >>> err) (unsafeCoerceEff <<< ok))
答案 0 :(得分:0)
EffWebGL
的定义如下in the library:
type EffWebGL eff a = Eff (webgl :: WebGl | eff) a
它只是Eff
的别名,但请注意,其效果行包括WebGl
效果。
当编译器尝试在您的函数中对此进行协调时,它会根据使用ok
作为回调来推断ok :: Eff (webgl | eff) a
,但是由于ok
回调必须具有相同的类型作为错误回调(来自makeAff
的签名),编译器还会推断出err :: Eff (webgl | eff) a
,因此也推断出error >>> err :: Eff (webgl | eff) a
。但是,由于error >>> err
用作runWebGL
的参数,因此它意味着error >>> err :: Eff eff a
(这就是runWebGL
的定义方式)。因此,编译器现在有两个必须为真的信息:
(1) error >>> err :: Eff (webgl | eff) a
(2) error >>> err :: Eff eff a
当然,这必须表示(webgl | eff) === eff
。因此eff
是其自身定义的一部分。又名“无限类型”。这就是为什么您会收到错误消息。
现在,为了修复它,您必须将参数err
设为Eff (webgl | eff) a
(根据makeAff
类型的要求),然后将其传递给runWebGL
为Eff eff a
(根据runWebGL
类型的要求)-即效果行会随着从内部回调流向外部回调而扩大。这应该是绝对安全的,因为内部回调永远不会使用这种效果(如其类型所示),但是,编译器没有一种安全的方法来执行此操作-这可能是该效果的原因之一行在PureScript 0.12中被抛弃了(很好!)
相反,您必须使用类型不安全的方式from Control.Monad.Eff.Unsafe
:
unsafeCoerceEff :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a
只需将错误回调包装在对此函数的调用中,它将起作用:
runWebGLAff arg = makeAff (\err ok -> runWebGL arg (unsafeCoerceEff $ error >>> err) ok)
P.S。通常,我建议您切换到PS 0.12,但似乎您不能这样做,因为WebGL库尚未更新(还好吗?)。