尝试在Rascal中实现Result类型和partial()时出现类型问题

时间:2018-08-09 14:20:47

标签: rascal

尝试在Rascal中实现Result / Maybe和partial()时出现类型问题

下面您会发现我尝试实现Result类型,包括Bind和Pure(aka return)函数。 在我将各个部分放在一起之前,一切似乎都很好。

  1. 首先,即使执行产生预期的值和类型,IDE也会在(*)处检测类型问题。
  2. 第二,在执行代码(**)时,值是预期的,即使类型不是我期望的也很难。
    • 结果类型为:结果[&S,&E]:确定(香蕉(“香蕉”))
    • 我希望输入以下类型:结果[香蕉,未定义]:Ok(香蕉(“香蕉”))

另一方面,当我使用第二个绑定实现(bindR2)时,测试(***)失败,并在调用中出现以下异常:partial(bindR2,functionA)(PureR(Apple(“ Apple”)))。 这里的错误是:

project:///src/Result.rsc|(964,10,<39,80>,<39,90>):  Expected Result[Apple,&E], but got Result[Banana,Undefined]

哪个显示了我期望的结果值和类型,但是Rascal期望了另一个类型。

我想知道我是否在此代码中错误地使用了类型变量,还是我没有正确使用类型系统?

module Result

import Exception;

public alias Undefined  = RuntimeException;
data Result[&S, &E] = Ok(&S) | Error (&E);

// PureR (aka return)
public Result[&S, &E] PureR(&S s) = Ok(s);

// bindR. first implementation of bind,
public Result[&S, &E] bindR( ( Result[&S, &E] ( &Sin ) ) f, Result[&Sin, &E] xR) {
    switch (xR) {
        case Ok(x)    : return f(x);
        case Error(e) : return Error(e);
    }
}

// bindR2. Second implementation of bind,
public Result[&S, &E] bindR2( ( Result[&S, &E] ( &Sin ) ) f, Ok(x)    ) = f(x);
public Result[&S, &E] bindR2( ( Result[&S, &E] ( &Sin ) ) f, Error(e) ) = Error(e);

// Tests BindR
// test helpers
public data Apple  = Apple(str);
public data Banana = Banana(str);
public int add(int x, int y) = x + y; 
public Result[num, void] fb(&Success <: num x) = Ok(x*3);
public Result[Banana,  Undefined] functionA (Apple apple) = Ok(Banana("banana"));

test bool testBindResult1() = bindR(fb, Ok(3))      == Ok(9);
test bool testBindResult2() = bindR2(fb, Ok(3))     == Ok(9);
test bool testBindResult3() = bindR(fb, Error([]))  == Error([]);
test bool testBindResult4() = bindR2(fb, Error([])) == Error([]);
test bool testBindResult5() = bindR(functionA, PureR(Apple("apple")))  == Ok(Banana("banana"));
test bool testBindResult6() = bindR2(functionA, PureR(Apple("apple"))) == Ok(Banana("banana")); // (*) <-- Type checker warning

// partial application.
public (&T (&X2)) partial( (&T (&X1, &X2)) f, &X1 x1 ) = (&T)( &X2 x2 ) { return f(x1, x2); };

// Test partial on BindR and BindR2
// Test
test bool testPartialAdd() = partial(add, 3)(3) == 6;
test bool testPartialBindR() = partial(bindR, functionA)(PureR(Apple("Apple"))) == Ok(Banana("banana")); // (**) <-- Type checker warning
// ERROR: test bool testPartialBindR2() = partial(bindR2, functionA)(PureR(Apple("Apple"))) == Ok(Banana("banana")); // (***) <-- Runtime type error.

当我排查类型检查器显示的部分错误时(partial(bindR, functionA)下的**处的红色波浪线),它显示以下内容:

Function of type
1. ...fun
2. ...... fun &T <: value ( &X2 <: value )
3. ...........( fun &T <: value                      ( &X1 <: value,                                          &X2 <: value                      ), &X1 <: value                             )
cannot be called with argument types 
4. .............fun Result[&S <: value, &E <: value] ( fun Result[&S <: value, &E  <: value] (&Sin <: value), Result[&Sin <: value, &E <: value]), fun Result[Banana, RuntimeException](Apple)

2是部分函数,​​其求值结果为&X2的函数,en产生类型为&T的值。
3是输入的预期类型。
输入的类型为4。

所有类型似乎都排成一列

  • &T <: valueResult[&S <: value, &E <: value]

  • 对齐
  • &X1 <: valuefun Result[&S <: value, &E <: value] (&Sin <: value)

  • 对齐
  • &X2 <: valueResult[&Sin <: value, &E <: value]

  • 对齐
  • &X1 <: valuefun Result[Banana, RuntimeException](Apple)

  • 对齐

这也表明&X1被提及两次。一次使用类型变量,一次在代码中提供函数的类型。

在大多数代码中,我看到类型系统能够解析类型变量的类型,在这种情况下为&S,&E和&Sin。 &S应该解析为Banana,&E应该解析为RuntimeException,而&Sin应该解析为Apple。

1 个答案:

答案 0 :(得分:0)

很好的问题。

  • 类型检查器仍处于beta中,并可能产生虚假错误和警告。口译员现在将忽略它们。
  • 我怀疑运行时类型确实是Result[Banana, Undefined],您可以使用类型库模块中的typeOf函数进行检查。 println("<typeOf(x)>")
  • 如果是这样,则此{c,w}可能是类型解释错误(在生成高阶函数的情况下忘记实例化类型参数的一个级别,???)?变量类型,在解释结果旁边。请将此问题提交?
  • (假设的)错误还可以解释第二种实现的运行时失败,该实现会在意外的非实例化类型参数上检查子类型,并对此失败。