我正在使用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)
答案 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