haskell - 在 raku 的模块中使用 Haskell 之类的 Prelude 模块
问题描述
我正在编写一个包含一些部分的绘图包,并且我的运算符和数据类型分散在各处。但是我不希望用户每次都添加相应的模块,因为它会很混乱,例如我会有一个Point
类,一个Monoid
角色和一个Style
类在不同的路径中,像这样
unit module Package::Data::Monoid;
# $?FILE = lib/Package/Data/Monoid.pm6
role Monoid {...}
unit module Package::Data::Point;
# $?FILE = lib/Package/Data/Point.pm6
class Point {...}
unit module Package::Data::Style;
# $?FILE = lib/Package/Data/Style.pm6
class Style {...}
我想有一个haskell
类似的前奏lib/Package/Prelude.pm6
,我可以写这样的脚本
use Package::Prelude;
# I can use Point right away, Style etc...
而不是做
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
# I can too use point right away, but for users not knowing the
# inner workings it's too overwhelming
我尝试了很多事情:
- 这个版本没有给我正确的效果,我必须输入整个指向的路径,即
Package::Data::Point
...
unit module Package::Prelude;
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
- 这个版本
Point
马上就给了我,但我遇到了操作符等问题,我也想自动添加来自上述示例包中导出例程的所有内容。
# $?FILE = lib/Package/Prelude.pm6
use Package::Data::Style;
use Package::Data::Point;
use Package::Data::Monoid;
sub EXPORT {
hash <Point> => Point
, <Style> => Style
, <mappend> => &mappend
...
}
你们知道获得这种类似前奏曲文件的更好更快的方法吗?
解决方案
使用EXPORT
方向正确。需要了解的关键事项是:
- 导入是词法的
- 我们可以使用自省来获取和访问当前词法范围内的符号
所以配方是:
use
里面的所有模块EXPORT
- 然后提取所有导入的符号并将它们作为结果返回
EXPORT
例如,我创建了一个模块Foo::Point
,包括一个运算符和一个类:
unit module Foo::Point;
class Point is export {
has ($.x, $.y);
}
multi infix:<+>(Point $a, Point $b) is export {
Point.new(x => $a.x + $b.x, y => $a.y + $b.y)
}
而且,只是为了证明它可以与多个模块一起使用,还有一个Foo::Monad
:
unit module Foo::Monad;
class Monad is export {
method explain() { say "Just think of a burrito..." }
}
目标是使这项工作:
use Foo::Prelude;
say Point.new(x => 2, y => 4) + Point.new(x => 3, y => 5);
Monad.explain;
这可以通过编写一个Foo::Prelude
包含以下内容来实现:
sub EXPORT() {
{
use Foo::Point;
use Foo::Monad;
return ::.pairs.grep(*.key ne '$_').Map;
}
}
这里有一些奇怪的地方需要解释:
- A
sub
具有 、 和 的隐$_
式$/
声明$!
。use
当模块为'd时,导出这些将导致编译时符号冲突错误。一个块只有一个隐含的$_
. 因此,我们使用嵌套的裸块使我们的生活更轻松。 - 这
grep
是为了确保我们不会导出隐式声明$_
的符号(感谢嵌套块,这是我们唯一需要关心的)。 ::
是引用当前范围的一种方式(词源:::
是包分隔符)。::.pairs
从而获得Pair
当前范围内每个符号的对象。
有一种推测的重新导出机制可能会出现在未来的 Raku 语言版本中,这将消除对这种样板文件的需求。
推荐阅读
- mysql - 结合两个mysql查询返回ok而不是rows
- php - 变量的值不能通过 php 中的条件准确地得到
- angular - Angular 2 嵌套路由问题(未捕获(承诺中):TypeError:无法读取 null 的属性“组件”)
- mysql - 插入删除后的 SQL 触发器
- casting - 名单演员表
列出 在科特林 - xamarin - 如何解决类型 SendBirdException 错误?
- wpf - STAThread 方法属性和线程单元状态有什么区别?
- machine-learning - 如何为像素级预测计算交叉熵
- c# - 如何调用具有布尔值true unity C# 的数组元素
- ruby-on-rails - 在 RubyMine 中执行测试会导致 Windows 7 上出现“未初始化的常量 Spring::Client::Run::UNIXSocket”