Idris解析器组合GADT

时间:2016-03-19 21:54:51

标签: parsing types gadt idris

我目前正致力于在Idris中实现一个简单的解析器组合库,以便学习语言并更好地理解类型系统,但是我在解决如何声明和使用GADT方面遇到了一些麻烦。我试图制定的解析器数据类型看起来像(在Haskell中):type Parser a = String -> [(a,String)],来自the source论文。基本上,类型是一个接受字符串并返回列表的函数。

在伊德里斯,我有:

data Parser : Type -> Type where
    fail : a -> (String -> [])
    pass : a -> (String -> [(a,String)])

其中fail实例是一个始终失败的解析器(即 - 将是一个始终返回空列表的函数),pass实例是一个消耗某些符号的解析器。将上述内容加载到解释器中时,出现错误,即List elem与预期类型Type之间存在类型不匹配。但是,当我使用:t String -> List Type检查repl中返回的解析器类型时,我得到Type,看起来应该可以正常工作。

如果有人能够很好地解释为什么这个数据声明不起作用,或者是表示解析器数据类型的更好的替代方法,我将非常感激。

2 个答案:

答案 0 :(得分:2)

在定义数据类型Parser时,第一行是说此类型采用类型并返回一个类型,在这种情况下,它需要a并返回Parser a

因此,您的构造函数应该返回Parser a

类似于Lista并返回List a

您当前在构造函数中返回的内容不属于Parser类型 - 很容易看出单词Parser出现在右侧。

除此之外,我不确定你最能代表这一点。 但是,有一些解析器库已经在Idris中编写,看看这些可能有帮助吗?例如,看看这个库列表,解析器是第一个提到的: - Idris libraries

答案 1 :(得分:2)

在Haskell,

Parser : Type -> Type
Parser a = String -> List (a, String)

不会创建新类型,它只是一种类型的同义词。你可以在Idris做类似的事情

Parser a

然后将助手定义定义为返回fail : Parser a fail = const [] pass : a -> Parser a pass x = \s => [(x, s)] s:

的简单函数
    //Controller in app.js 
    app.controller('galleryCtrl', ['$scope', '$http','$location',
           function ($scope, $http, $location) {
               $scope.ink = {
                    header: "Personalized Ink Products",
                    imageArray:  [

                    'ink-1.jpg', 
                    'ink-2.jpg',  
                    'ink-3.jpg',
                    'ink-4.jpg'
                    ]

           };
}]); 
    //my directive in app.js
app.directive('pictureGallery', function () {
    return {
        templateUrl: 'directives/picturegallery.html',
        replace: true,
        scope: {
            inkObject: '='

            }
    }

});

//the template

<div class="top-space">
    <h1>{{ inkObject.header }}</h1>
    <div class="row">
        <div class="col-xs-6 col-sm-4 col-md-4" ng-repeat="image in {{ inkObject.imageArray }}">
            <a href="img/{{image}}" target="_blank">
            <img ng-src="img/{{image}}"  width="200px" height="200px" 
            class="img-responsive img-thumbnail bottom-space"> 
            </a>  
        </div>
    </div>
</div>


//the view
<picture-gallery  ink-object="ink"> </picture-gallery>