0

我已经问过关于 undefined 的问题。而且因为不可能做这样的事情,所以我将描述这可能有用的情况。但我认为这个问题很常见,在其他情况下也很有用。

让我们想象一种情况,当我们为某些语法编写解析器时。我们定义了由许多数据类型实现的 AST,每个数据类型都有一组构造函数,每个构造函数都有一组参数。每种类型都派生自 Show。然后我们开始编写解析器实现,我们在其中定义了许多具有递归依赖关系的函数。

由于我们有许多功能,因此很难在没有检查的情况下一次编写整个模块。但是函数循环引用不允许编译未完成的模块。在这种情况下,我定义了不期望返回所需类型的值的钩子函数。

这是一个问题!函数必须返回的不是简单类型,而是构造函数中带有构造函数的数据构造函数。这对于钩子函数来说太难了。所以我这样做:

parseHook _ = undefined

一切都很简单,直到“未定义”不在结果数据树中。我想指出这种情况发生在发展阶段,我唯一想要的就是看到树结构。当然,我可以将每种类型都包装在“Maybe”中,但我不想更改已经存在的类型。

英语不是我的母语,所以我不确定我是否正确地表达了我的想法。这就是为什么我想添加一个这种情况的例子:

data StructParam = StructParam Int Int
                 deriving Show 

data Struct1 = Struct1 Int Int StructParam Int Int Int Int StructParam
             deriving Show 

data Struct2 = Struct2 Int Int StructParam Int Int Int Int StructParam  
             deriving Show 

data Struct3 = Struct3_var1 Struct1 
             | Struct3_var2 Struct2
             deriving Show 

-- this hook is ok, but too long
parse1 _ = Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam 9 0)

-- this hook is short, but undefined
parse2 _ = undefined

-- complete function
rootParse 1 = Struct3_var1(parse1 1)    
rootParse 2 = Struct3_var2(parse2 2)

>print $ rootParse 1
Struct3_var1 (Struct1 1 2 (StructParam 3 4) 5 6 7 8 (StructParam 9 0))

>print $ rootParse 2
Prelude.undefined

-- but I want something like this
>print $ rootParse 2
Struct3_var2("undefined")
4

2 回答 2

10

您可以在数据类型中添加“未实现”作为构造函数,为所有以定义结尾的解析设置默认情况Unimplemented,然后显示实例将正常工作。

data Exp = Literal Int
         | Variable String
         | Operator Op Exp Exp
         | Unimplemented

    deriving Show
于 2012-05-25T12:36:02.583 回答
0

可能实现这一点的一个丑陋的技巧是在这个类的 Show-instance 中使用unsafePerformIOcatch来检测 undefined 抛出的异常。不过,我不推荐这种方法。

于 2012-05-25T13:41:49.080 回答