Haxe:使用摘要定义类型组

时间:2018-08-05 00:15:02

标签: abstract haxe

我已经在Haxe中找到了有关摘要的信息,我正在尝试创建一个示例项目来学习如何使用它们。

到目前为止,我已经阅读了https://haxe.org/manual/types-abstract.htmlhttps://haxe.org/blog/abstracting-primitives/http://old.haxe.org/manual/abstractshttps://code.haxe.org/category/other/passing-different-types-to-a-function-parameter.html。如果有人有其他材料可以指导我,我将不胜感激。

我基本上是在尝试创建一个函数,该函数将接受类型为StringIntFloatBool的变量,并对其进行跟踪。但是,当我尝试使用haxe -main Main -cpp Export进行编译时,我有点卡住了:abstracts/Comparison.hx:99: characters 42-43 : Type not found : A。我正试图找出原因,并加以解决。

我觉得我要附加太多代码,但这是我到目前为止编写的内容:

Main.hx

import abstracts.*;

class Main
{
    public static function main()
    {
        var toPrint:Array<String> = ["String1", "String2", "String3"];
        printArray(toPrint);
    }

    public static function printArray(toPrint:PrintableArray)
    {
        for (element in toPrint)
        {
            trace(element);
        }
    }
}

abstracs / Comparison.hx

package abstracts;

enum Either<A, B>
{
    Left(v:A);
    Right(v:B);
}

abstract Of2<A, B>(Either<A, B>) from Either<A, B> to Either<A, B>
{
    @from inline static function fromA<A, B>(a:A):Of2<A, B>
    {
        return Left(a);
    }
    @from inline static function fromB<A, B>(b:B):Of2<A, B>
    {
        return Right(b);
    }

    @to inline static function toA():Null<A>
    {
        return switch (this)
        {
            case Left(a): a;
            default: null;
        }
    }
    @to inline static function toB():Null<B>
    {
        return switch (this)
        {
            case Right(b): b;
            default: null;
        }
    }
}

abstract Of3<A, B, C>(Either<Either<A, B>, C>) from Either<Either<A, B>, C> to Either<Either<A, B>, C>
{
    @from inline static function fromA<A, B, C>(a:A):Of3<A, B, C>
    {
        return Left(Left(a));
    }
    @from inline static function fromB<A, B, C>(b:B):Of3<A, B, C>
    {
        return Left(Right(b));
    }
    @from inline static function fromC<A, B, C>(c:C):Of3<A, B, C>
    {
        return Right(c);
    }

    @to inline static function toA():Null<A>
    {
        return switch (this)
        {
            case Left(Left(a)): a;
            default: null;
        }
    }
    @to inline static function toB():Null<B>
    {
        return switch (this)
        {
            case Left(Right(b)): b;
            default: null;
        }
    }
    @to inline static function toC():Null<C>
    {
        return switch (this)
        {
            case Right(c): c;
            default: null;
        }
    }
}

abstract Of4<A, B, C, D>(Either<Either<A, B>, Either<C, D>>) from Either<Either<A, B>, Either<C, D>> to Either<Either<A, B>, Either<C, D>>
{
    @from inline static function fromA<A, B, C, D>(a:A):Of4<A, B, C, D>
    {
        return Left(Left(a));
    }
    @from inline static function fromB<A, B, C, D>(b:B):Of4<A, B, C, D>
    {
        return Left(Right(b));
    }
    @from inline static function fromC<A, B, C, D>(c:C):Of4<A, B, C, D>
    {
        return Right(Left(c));
    }
    @from inline static function fromD<A, B, C, D>(d:D):Of4<A, B, C, D>
    {
        return Right(Right(d));
    }

    @to inline static function toA():Null<A>
    {
        return switch (this)
        {
            case Left(Left(a)): a;
            default: null;
        }
    }
    @to inline static function toB():Null<B>
    {
        return switch (this)
        {
            case Left(Right(b)): b;
            default: null;
        }
    }
    @to inline static function toC():Null<C>
    {
        return switch (this)
        {
            case Right(Left(c)): c;
            default: null;
        }
    }
    @to inline static function toD():Null<D>
    {
        return switch (this)
        {
            case Right(Right(d)): d;
            default: null;
        }
    }
}

摘要/Printable.hx

package abstracts;

abstract Printable(Comparison.Of4<String, Int, Float, Bool>) {}

摘要/PrintableArray.hx

package abstracts;

abstract PrintableArray(Array<Printable.Printable>) {}

非常感谢!

3 个答案:

答案 0 :(得分:0)

Type not found : A错误是由于尝试在静态函数中访问类型为 instance 的类型参数引起的。静态函数只能访问在函数本身上声明的类型参数。 @:to方法不一定是static,因此您只需删除关键字即可。

但是还有更多问题:

  • 您使用了@from@to而不是@:from@:to,这意味着您的转换方法没有任何作用。
  • 即使更改为@:from,编译器也不知道如何处理fromA / fromB / fromC / fromD,因为它们看起来都一样他也一样类型参数是在静态方法上声明的,因此没有具体的String / Int / etc类型可以作为选择的基础。您可能需要具体的fromString / fromInt /等功能。
  • 抽象的隐式强制转换是不可传递的see example at the bottom here)。这意味着您的Printable摘要根本不允许任何隐式转换。相反,它可能是一个简单的typedef

    typedef Printable = Comparison.Of4<String, Int, Bool, Float>;
    
  • 类似地,您不能在iterator() methodforwarded的情况下,例如PrintableArray遍历@:forward(iterator)。但这可能会导致出现诸如here之类的差异问题。您还缺少隐式转换from Array<Printable>-简而言之,typedef会更简单。

  • 即使解决了以上所有问题,您的trace()也不会具有所需的输出。隐式@:to强制转换是编译时功能,因此此处不应用强制转换,并且trace()接受Dynamic。您最终将得到如下结果:

    source/Main.hx:15: Left(Left(String1))
    

    您必须在摘要中添加一个toString()方法,以避免打印包装器枚举:

    function toString():String {
        return Std.string(switch this {
            case Left(Left(v)): v;
            case Left(Right(v)): v;
            case Right(Left(v)): v;
            case Right(Right(v)): v;
        });
    }
    

答案 1 :(得分:0)

  

我基本上是在尝试使函数接受类型为StringIntFloatBool的变量。

如果这是问题的核心,则您可能还会查看我的overload库。它是一个宏,允许在Haxe中重载函数。它在编译时根据输入的类型决定要调用的函数。与haxe.ds.Either(又名Left / Right)相比,它具有一些优势,即它是一种编译时功能,没有运行时开销。还有一些缺点:函数在运行时不容易被调用,或者使用动态输入,必须在编译时知道类型。

答案 2 :(得分:0)

我发现有些东西可以解决一些运行时开销:

WorkItems

似乎工作得很好,但是您必须调用val model = new RandomForestRegressor() .setFeaturesCol("features") .setLabelCol("label") .setImpurity("gini") .setMaxBins(20) .setMaxDepth(20) .setNumTrees(50) 才能获得文字值。它还可以为您提供值类型的索引,并且具有静态扩展名,可读性很强:

Exception in thread "main" java.lang.IllegalArgumentException: 
rfr_dc9303ee1fc9 parameter impurity given invalid value gini.
[error]     at org.apache.spark.ml.param.Param.validate(params.scala:78)
[error]     at org.apache.spark.ml.param.ParamPair.<init>(params.scala:656)
[error]     at org.apache.spark.ml.param.Param.$minus$greater(params.scala:87)
[error]     at org.apache.spark.ml.param.Params.set(params.scala:737)
[error]     at org.apache.spark.ml.param.Params.set$(params.scala:736)
[error]     at org.apache.spark.ml.PipelineStage.set(Pipeline.scala:42)

Here's a script,它将制作更大的Multimorph软件包。