有没有一种方法可以实现类型为((a-> b)-> b)-> ab的函数?


18

命题(P -> Q) -> QP \/ Q是等价的。

有没有办法在Haskell中见证这种等效性:

from :: Either a b -> ((a -> b) -> b)
from x = case x of
         Left a -> \f -> f a
         Right b -> \f -> b

to :: ((a -> b) -> b) -> Either a b
to = ???

这样

from . to = idto . from = id


在我看来,这似乎是不可能的,但也许我错了。如果是这样,一个有用的出发点就是具有完全多态类型的函数((a -> b) -> b)同构为a:唯一可能的实现是g f = f someHardcodedA
amalloy

1
@amalloy还有另一种可能的实现方式:g = const someHardcodedB
Fyodor Soikin

嗯当然了 是ab。说得通。
amalloy

1
如果Haskell拨打了电话/抄送,则to f = callcc (\k -> k (Right (f (\a -> k (Left a)))))可以使用。(这是含蓄的经典证明。)
benrg

Answers:


14

命题(P -> Q) -> QP \/ Q是等价的。

这在古典逻辑中是正确的,但在建构逻辑中却不是。

在构造逻辑中,我们没有排除中间定律,即我们不能以“ P为真或P为非真”开始思考。

传统上,我们的推理如下:

  • 如果P为true(即,我们有(x :: P)),则返回Left x
  • 如果P为假,那么用Haskell讲​​,我们将具有nx :: P -> Void功能。然后absurd . nx :: P -> Q(我们可以见顶任何类型的,我们采取Q),并呼吁给予f :: (P -> Q) -> Q)absurd . nx获得类型的值Q

问题在于,没有类型的一般功能:

lem :: forall p. Either p (p -> Void)

对于某些具体类型,例如Bool有人居住,所以我们可以写

lemBool :: Either Bool (Bool -> Void)
lemBool = Left True -- arbitrary choice

但是,总的来说,我们不能。


9

不,这是不可能的。考虑以下特殊情况Q = Void

Either P Q然后是Either P Void,与的同构P

iso :: P -> Either P Void
iso = Left

iso_inv :: Either P Void -> P
iso_inv (Left p)  = p
iso_inv (Right q) = absurd q

因此,如果我们有一个功能项

impossible :: ((P -> Void) -> Void) -> Either P Void

我们也可以有一个学期

impossible2 :: ((P -> Void) -> Void) -> P
impossible2 = iso_inv . impossible

根据Curry-Howard的对应关系,这将是直觉逻辑中的重言式:

((P -> False) -> False) -> P

但是以上是双重否定消除,众所周知,在直觉逻辑中不可能证明这是矛盾的。(我们可以用经典逻辑证明这一事实是不相关的。)

(最后的注:这假设Haskell程序终止了。当然,使用无限递归undefined和类似的方法实际上避免返回结果,我们可以在Haskell中使用任何类型。)


4

不,不可能,但这有点微妙。问题在于类型变量ab被普遍量化。

to :: ((a -> b) -> b) -> Either a b
to f = ...

a并被b普遍量化。调用者选择它们的类型,因此您不能仅创建任何一种类型的值。这意味着您不能Either a b在忽略参数的情况下仅创建类型的值f。但是使用f也是不可能的。不知道是什么类型ab是什么,就无法创建a -> b要传递给type的值f。当类型被普遍地量化时,只是没有足够的可用信息。

至于为什么同构在Haskell中不起作用-您确定这些命题在建设性直觉主义逻辑中是等效的吗?Haskell没有实现经典的演绎逻辑。


2

正如其他人指出的那样,这是不可能的,因为我们没有被排除的中间律。让我更明确地说明这一点。假设我们有

bogus :: ((a -> b) -> b) -> Either a b

然后我们开始b ~ Void。然后我们得到

-- chi calls this `impossible2`.
double_neg_elim :: ((a -> Void) -> Void) -> a
bouble_neg_elim f = case bogus f of
             Left a -> a
             Right v -> absurd v

现在,让我们证明适用于特定命题的被排除中间律的双重否定。

nnlem :: forall a. (Either a (a -> Void) -> Void) -> Void
nnlem f = not_not_a not_a
  where
    not_a :: a -> Void
    not_a = f . Left

    not_not_a :: (a -> Void) -> Void
    not_not_a = f . Right

所以现在

lem :: Either a (a -> Void)
lem = double_neg_elim nnlem

lem显然不存在,因为a可以编码我碰巧选择的任何图灵机配置都将停止的命题。


让我们验证lem是否足够:

bogus :: forall a b. ((a -> b) -> b) -> Either a b
bogus f = case lem @a of
  Left a -> Left a
  Right na -> Right $ f (absurd . na)

0

我不知道这在逻辑上是否有效,或者对您而言是什么意思,但是可以在Haskell中编写这样的函数。

要构造一个Either a b,我们需要一个a或一个b值。我们没有任何构造a值的方法,但是我们确实有一个函数返回b可以调用的a。为此,我们需要提供一个将an转换a为a 的函数b,但是鉴于类型是未知的,我们最多只能使它返回一个常数b。为了获得该b值,我们无法以其他任何方式构造它,因此这成为循环推理-我们可以通过简单地创建一个固定点来解决该问题:

to :: ((a -> b) -> b) -> Either a b
to f = let x = f (\_ -> x) in Right x
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.