在模式匹配表达式中"标记"无法访问的案例的标准方法是什么?例如,对于Aeson,我有Value并需要解压缩它.我用模式匹配来做,我知道它是Object,它不是Array,String,Number等,因为我创建了它.所以,我会有案例_ -> something.一定是something什么?我的意思是标准的Haskell,而不是LiquidHaskell方法:)它是类似的error "Internal error"还是别的?
具有不可能的构造函数在Haskell中是常见的,并且可以根据情况和样式以两种方式之一处理.许多开发人员,特别是那些喜欢Haskell 98代码风格的开发人员,只会通过错误指出不可能的情况:
data SumType1 = ConstrA | ConstrB | ConstrC
anyConstr :: SumType1 -> Int
anyConstr ConstrA = 1
anyConstr ConstrB = 2
anyConstr ConstrC = 3
onlyConstrA :: SumType1 -> Int
onlyConstrA ConstrA = 1
onlyConstrA _ = error "Impossible: internal error, passed wrong constructor."
Run Code Online (Sandbox Code Playgroud)
然而,这既不令人满意,并且要求开发人员在编译器能够并且更可靠时确保安全性.常见的解决方案是使用只能代表ConstrA的类型.你可以得到SumType1两种类型的总和,其中一种类型的字段是"ConstrAType",但这种重构可能真的在耗尽.有时我更喜欢GADT解决方案:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
data SumTag = A | Anything
data SumType (a :: SumTag) where
ConstrA :: SumType A
ConstrB :: SumType Anything
ConstrC :: SumType Anything
doAnything :: SumType a -> Int
doAnything ConstrA = 1
doAnything ConstrB = 2
doAnything ConstrC = 3
onlyConstrA :: SumType A -> Int
onlyConstrA ConstrA = 1
Run Code Online (Sandbox Code Playgroud)
现在该函数onlyConstrA有一个清晰显示的类型(当与数据声明一起考虑时)它只能应用于ConstrA构造函数.同时我们没有失去任何力量,例如doAnything不需要考虑原始SumType1的多毛二分为各种类型 - 构造函数都来自相同的原始类型.