统一记录类型

Unifying record type

作为学习练习,我正在尝试定义一个新类型作为函数的持有者,这些函数可以将 Show-able 值转换为 Effects,即:

newtype ShEff a = ShEff (forall eff. Show a => a -> Eff eff Unit)

然而,这:

f :: forall a. ShEff a
f = ShEff logShow

编译失败并出现此错误:

  Could not match type

    ( console :: CONSOLE
    | t2
    )

  with type

    eff1


while trying to match type Eff
                             ( console :: CONSOLE
                             | t2
                             )
  with type Eff eff1
while checking that expression logShow
  has type t0 -> Eff eff1 Unit
in value declaration f

你能给我指出正确的方向吗?

logShow的类型是

forall eff. Show a => a -> Eff (console :: CONSOLE | eff) Unit

所以你不能将它存储在 ShEff 中,因为它必须适用于 every eff,而 logShow 仅适用于包含 CONSOLE 效果的行。

您有两个选择:

  1. eff 类型参数移到 ShEff 之外:

    newtype ShEff eff a = ShEff (a -> Eff eff Unit)
    
    f :: forall a eff. Show a => ShEff (console :: CONSOLE | eff) a
    f = ShEff logShow
    
  2. ShEff内添加约束:

    newtype ShEff a = ShEff (forall eff. a -> Eff (console :: CONSOLE | eff) Unit)
    
    f :: forall a eff. Show a => ShEff a
    f = ShEff logShow
    

另请注意,在这两种情况下,我都将 Show a 约束移到了 ShEff 之外。