写一个没有 case 的空 case 的函数

Write a function with an empty case without case

我可以用一个空的 case 写一些不可能的东西,例如用 Decision 来使用它。

{-# LANGUAGE DataKinds, EmptyCase, LambdaCase, TypeOperators #-}

import Data.Type.Equality
import Data.Void

data X = X1 | X2

f :: X1 :~: X2 -> Void
f = \case {}
-- or
-- f x = case x of {}

有没有一种不使用 case 通过直接对参数进行模式匹配来编写等价物的方法?

f :: X1 :~: X2 -> Void
f ???

好吧,你可以使用可怕的 CPP hack:

{-# LANGUAGE CPP #-}
#define Absurd      = \case {}

f :: X1 :~: X2 -> Void
f Absurd   -- expands to "f = case {}"

但是,如果您正在寻找使用纯 Haskell 语法的解决方案,我很确定答案是否定的。与空案例不同,您不能在没有至少一种模式的情况下使用模式语法定义 f。而且,没有 GHC 将模式理解为无人居住类型术语的密码。 (即使有,也没有语法允许您定义没有 right-hand 边的 f pat。)

这是使用模式同义词的尝试。它并不完全令人满意,可能不是您真正想要的。它只能通过将 \case{} 移离您的眼睛来实现。我们在某些点上仍然需要使用absurd

{-# LANGUAGE PatternSynonyms, ViewPatterns, GADTs #-}
{-# LANGUAGE DataKinds, EmptyCase, LambdaCase, TypeOperators #-}

import Data.Type.Equality
import Data.Void

data X = X1 | X2

pattern Abs :: Void -> a
pattern Abs x <- (\case{} -> x)

f :: 'X1 :~: 'X2 -> Void
f (Abs x) = x

g :: 'X1 :~: 'X2 -> a
g (Abs x) = absurd x

{-
    Pattern match(es) are non-exhaustive
    In an equation for `h':
        Patterns of type 'X1 :~: 'X1 not matched: Refl
-}
h :: 'X1 :~: 'X1 -> Void
h (Abs x) = x

另一种方法是利用模板 Haskell。

我想如果你想模仿这个,最简单的方法类似于评论中发布的答案:

f _ = undefined

然而,这是懒惰的:

f (error "aw beans")  -- undefined

而空case是严格的:

(\ case {} :: X1 :~: X2 -> Void) (error "aw beans")  -- beans

所以更好的替代方法是 seq:

impossible :: a -> Void
impossible x = x `seq` impossible x

BangPatterns:

{-# Language BangPatterns #-}

impossible :: a -> Void
impossible !x = impossible x

那你就写f = impossible吧,我觉得挺好的。 (a 上的量词在逻辑上更像是“for any”而不是“for all”,但是哦,好吧。)你当然可以抛出一些稍微更具描述性的东西,而不是进入无限循环,以防情况不妙实际上不可能—error "the impossible was possible after all".

这也适用于 void 包中 Void 的 old-fashioned 定义为 data Void = Void !Voidnewtype Void = Void Void