为什么在没有类型应用程序的情况下某些函数调用无法工作?

时间:2018-12-26 18:07:34

标签: haskell

我无法理解类型应用程序的工作方式。当sing中对refuteRefuteKnockable的调用在没有类型应用程序的情况下无法进行类型检查时,为何sing中的knockableOrOpened无法在没有类型应用程序的情况下使用?

 refuteRefuteKnockable :: SingI s => Refuted (Refuted (Knockable s)) -> Knockable s
 refuteRefuteKnockable rrK =
   case isKnockable $ sing of
     Proved k -> k
     Disproved rK -> absurd $ rrK rK

 knockableOrOpened :: forall s. SingI s => Or Knockable ((:~:) Opened) s
 knockableOrOpened =
   case sing @s of
     SOpened -> OrRight $ Refl
     SClosed -> OrLeft KnockClosed
     SLocked -> OrLeft KnockLocked

我正在使用以下代码库:https://github.com/mstksg/inCode/blob/master/code-samples/singletons/Door3.hs

1 个答案:

答案 0 :(得分:7)

类型推断是原因。此类型包含./build/sbt package ...

s

所以

refuteRefuteKnockable :: SingI s => Refuted (Refuted (Knockable s)) -> Knockable s
                                                                       ^^^^^^^^^^^

必须具有类型 refuteRefuteKnockable rrK = case isKnockable $ sing of Proved k -> k ^^^ 。因此,推断出Knockable s的类型,可能也包含Proved k。这与s的类型相同,从中我们推断应该对isKnockable $ sing应用哪种类型(利用sing的签名)。 GHC为我们完成了所有这一切。

在后一个示例中,我们无法执行相同的推理。

isKnockable

是模棱两可的,因为即使三个分支必须返回已知类型,我们仍然可以使用与case sing of SOpened -> OrRight $ Refl SClosed -> OrLeft KnockClosed SLocked -> OrLeft KnockLocked 不同的类型调用sing并进行所有类型检查。由于没有唯一 s,因此推断无法正常工作。

请注意,上面我不得不猜测一些事情。如果您共享类型的定义,我们可能会更准确。 (即,s定义在哪里?SOpened等如何?)