如何与外部语境中的类型相关联

jul*_*icz 33 haskell types functional-programming ghc type-declaration

让我们考虑以下代码段:

blah :: a -> b -> a
blah x y = ble x where
    ble :: b -> b
    ble x = x
Run Code Online (Sandbox Code Playgroud)

这在GHC下编译得很好,这实际上意味着b第3行b与第一行不同.

我的问题很简单:有没有办法以某种方式将类型声明与ble外部上下文中使用的类型相关联,即类型声明blah

显然,这只是一个示例,而不是类型声明的真实用例.

Joh*_*n L 44

使用ScopedTypeVariables扩展可以实现这一点.您需要使用显式forall来将类型变量放入范围.

blah :: forall a b. a -> b -> a
blah x y = ble x where
    ble :: b -> b
    ble x = x
Run Code Online (Sandbox Code Playgroud)

尝试使用启用ScopedTypeVariables加载此定义会给出:

foo.hs:2:16:
    Couldn't match type `a' with `b'
      `a' is a rigid type variable bound by
          the type signature for blah :: a -> b -> a at foo.hs:2:1
      `b' is a rigid type variable bound by
          the type signature for blah :: a -> b -> a at foo.hs:2:1
    In the first argument of `ble', namely `x'
    In the expression: ble x
    In an equation for `blah':
        blah x y
          = ble x
          where
              ble :: b -> b
              ble x = x
Run Code Online (Sandbox Code Playgroud)

你可以告诉GHC将两个bs 解释为相同的类型,因为错误说明a并且b绑定在同一行上.


Tho*_*ing 16

如果您不想使用ScopedTypeVariables,则可以使用good ole fashion asTypeOf函数.

-- defined in Prelude
asTypeOf :: a -> a -> a
x `asTypeOf` y = x
Run Code Online (Sandbox Code Playgroud)
blah :: a -> b -> a
blah x y = ble x where
    ble x = x `asTypeOf` y
Run Code Online (Sandbox Code Playgroud)

当然,由于类型错误,这将无法编译.

更新:

我想指出,有时你可能需要做一些你想做的事情asTypeOf.以下是超级使用的示例,asTypeOf因为我不想考虑实际需要的案例asTypeOf.类似的解决方案对于现实世界的情况也是如此.

foo :: Bounded a => Maybe a -> a
foo m = x
  where
    x = maxBound -- Q: how do I make (x :: a) when given (Maybe a)?
    _ = Just x `asTypeof` m -- A: witchcraft!
Run Code Online (Sandbox Code Playgroud)