未定义和发展(第2部分)

use*_*768 0 haskell undefined

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

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

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

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

parseHook _ = undefined
Run Code Online (Sandbox Code Playgroud)

一切都很简单,直到"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")
Run Code Online (Sandbox Code Playgroud)

Don*_*art 10

您可以在数据类型中添加"未实现"作为构造函数,对于以定义结束的所有解析具有默认大小写Unimplemented,然后show实例将非常简单.

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

    deriving Show
Run Code Online (Sandbox Code Playgroud)

  • 好处是,一旦你相信你已经完成,你可以删除构造函数,类型检查器将告诉你是否真的完成了所有的实现. (10认同)