Jon*_*her 3 c haskell types algebraic-data-types data-structures
免责声明:我是一名学习C的Haskell程序员.在Haskell中,我们有数据声明
data No = NO
Run Code Online (Sandbox Code Playgroud)
NO没有任何解释作为数字.如果我们在C中有相同的东西,那么我们就可以做到
union MaybeInt { enum No no; int just;};
Run Code Online (Sandbox Code Playgroud)
这可以用来做一些事情,比如有一个初始化为No的数组.
int A[k];
for (int i = 0; i < k; i++)
A[i] = NO;
Run Code Online (Sandbox Code Playgroud)
这在进行记忆时非常有用,因为通常会有一些重新算法,它会在数组中查找并基于查找的值,或者进行递归调用.例如:(对于斐波那契数字)
fibMem (int k){
if (FIB[k] == NO)
compute fibMem(k-1) + fib(k-2) and store the result in FIB[k]
return FIB[k]
}
Run Code Online (Sandbox Code Playgroud)
当然,现在,我可以将FIB [i]初始化为一些荒谬的值,如-100,这适用于这个问题; 但是,给定一个任意的记忆例程,我不知道值的范围,这种解决方案是行不通的.
使用枚举类型的问题:我看到的第一件事,就是让我跳出座位说"是"是枚举类型.我想为什么不做类似enum No {no}; 嘛,用nos 初始化用于memoization的数组有问题.如果我喜欢的话,问题是no被定义为0我选择的数字常量.这是不能令人满意的,因为如果存储在数组中的值应该为零(或我选择的常量),那么当我进行检查时,A[i] == no它应该是这样的!因此,我最终会执行一个不需要的递归.
这给我们带来了问题1:如何在C中获得一个被视为标志的符号常量,这对于任何不同类型的东西都是无法比拟的?
现在,工会的问题.联盟将其所有字段存储在一个地址中.因此,例如,对maybeInt.just的更新会影响maybeInt.no的值.例如,
union MaybeInt maybeInt;
maybeInt.just=9;
printf("%d",maybeInt.just);
printf("%d",maybeInt.no);
Run Code Online (Sandbox Code Playgroud)
如果在C中存在某种不相交的联合类型,那么最好的是,如果我使用了联合的一个值,则另一个变得无法获得.
这将我们带到第二个也是最后一个问题:如何在C中获得不相交的联合类型 - 这是一种具有许多可能变体的类型,但在任何给定时间只有一个.我希望能够做一些事情,比如:
disjoint T {type1 name1 , .... };
Run Code Online (Sandbox Code Playgroud)
如果设置了T.name2,则对T.name1的引用会引发错误.或者甚至更好地提及T必须经过某种区分.
如果这不能很好地完成,请解释原因.
Ker*_* SB 10
受歧视的联盟是一种非常标准的C语言.您只需将标记与数据分开:
struct Data
{
enum DataType
{
NotSet,
Integer,
Infinity,
Message
} tag;
union ValueType
{
int n;
char const * msg;
} data;
};
Run Code Online (Sandbox Code Playgroud)
现在您只需要维护标记规则,即只读取适合给定标记的值,并在写入union成员后更新标记.例如:
void foo(struct Data const * x)
{
switch (x->tag)
{
case NotSet: // ...
case Integer: // use x->data.n
case Infinity: // ...
case Message: // use x->data.msg
};
x->data.msg = "Thank you!";
x->tag = Message;
}
Run Code Online (Sandbox Code Playgroud)