Haskell:使用ExistentialQuantification并收到错误:无法匹配预期类型

时间:2018-03-23 10:18:02

标签: haskell

我正在使用ghc扩展ExistentialQuantification并且遇到错误。我知道s类型test的第二个参数与s函数中定义的test不一样,但我怎么能强迫它们相同?

1. {-# LANGUAGE ExistentialQuantification #-}
2.
3. data Func = forall s . Func s
4.
5. test :: (s -> a) -> Func -> a
6. test f (Func s) = f s

出现错误:

Untitled..hs:6:21: error:
    • Couldn't match expected type ‘s’ with actual type ‘s1’
      ‘s1’ is a rigid type variable bound by
        a pattern with constructor: Func :: forall s. s -> Func,
        in an equation for ‘test’
        at Untitled..hs:6:9
      ‘s’ is a rigid type variable bound by
        the type signature for:
          test :: forall s a. (s -> a) -> Func -> a
        at Untitled..hs:5:9
    • In the first argument of ‘f’, namely ‘s’
      In the expression: f s
      In an equation for ‘test’: test f (Func s) = f s
    • Relevant bindings include
        s :: s1 (bound at Untitled..hs:6:14)
        f :: s -> a (bound at Untitled..hs:6:6)
        test :: (s -> a) -> Func -> a (bound at Untitled..hs:6:1)

1 个答案:

答案 0 :(得分:3)

双重存在量化(∃)是通用量化(∀)。需要双重因素,因为传入函数在逆变位置中具有s(即它位于函数箭头的左侧)。将通用量化函数作为参数传递使test rank-2类型,因此您需要该扩展名。

{-# LANGUAGE Rank2Types #-}

test :: (forall s . s -> a) -> Func -> a
test f (Func s) = f s

但是,请注意,您实际上无法以任何有意义的方式使用它,因为如果无法知道类型,传入的函数不能对其参数执行任何操作。您可能希望为存在主义和通用添加一些约束。喜欢(我正在使用我更喜欢的语法)

{-# LANGUAGE GADTs, UnicodeSyntax #-}

data Func where
  Func :: Show s => s -> Func

test :: (∀s . Show s => s -> a) -> Func -> a
test f (Func s) = f s

一个可能更好的选择是完全避免存在量化(often used in a way that's not really Haskell-idiomatic),有利于参数多态:

data Func s = Func s

test :: (s -> a) -> Func s -> a 
test f (Func s) = f s