D 中的特征可以用于类型类吗?

2024-04-25

我是 D 新手,我正在寻找一种使用类似 Haskell 的类型类进行编程的好方法,例如D 中的函子、幺半群等。

Tango 或 Phobos 中是否实现了类似的功能?

我听说过可以对某些属性进行编译时类型检查的特征。它们可以用于类型类吗?

我尝试了一些模板专业化并提出了这个:

// Monoid.d
// generic Monoid gets called when there is no instance of Monoid for Type T
class Monoid(T) {
    pragma(msg, "Type is not a Monoid");
}

// Monoid instance for double
class Monoid(T:double) {
    static T mzero() { return 0; }
    static T mappend(T a, T b ) { return a + b;}
}

// Monoid instance for int
class Monoid(T:int) {
    static T mzero() { return 0; }
    static T mappend(T a, T b ) { return a + b;}
}

类型参数需要为 Monoid 的通用算法可以表示为:

template genericfunctions() {
    T TestMonoid(T,N = Monoid!T)(T a) {
        return N.mappend(N.mzero(),a);
    }
}

然而,如果你想省略模板参数,你必须导入所有需要的 Monoid 实例并混合genericfunctions模板。

import Monoid;
import std.stdio;
import std.conv;
mixin genericfunctions;

void main() {
    writefln(to!string(TestMonoid(3))); 
    writefln(to!string(TestMonoid(3.3243))); 
}

您现在可以使用整数和双精度数作为 Monoids。

然而,当你有像 Functor 这样的类型类,其实例本身是通用的时,事情会变得更加复杂:

module Functors;

// generic Functor like generic Monoid
class Functor(alias T, A) {
    pragma(msg,"Not an instance of Functor");
}

// very simple container to demonstrate functors behavior
class FunctorTest(A) {
    public A a; 
    this(A a) {
        this.a = a; 
    }
}

// instance of Functor for FunctorTest!A 
class Functor(alias T:FunctorTest,A) {
    static T!B fmap(B)(T!A a, B delegate(A) fn) {
        return new T!B(fn(a.a));
    }
}

一种算法如下所示:

template genericfunctions() {
    T TestMonoid(T,N = Monoid!T)(T a) {
        return N.mappend(N.mzero(),a);
    }

    // F is the Functor, A the functors type before,
    // B the functors Type after, N is the instance of Functor
    F!B fmap(alias F,A,B,N=Functor!(F,A))(F!A a, B delegate(A) fn) {
        return N.fmap!B(a,fn);
    }
}

幸运的是,您在使用它时可以省略四个模板参数:

mixin genericfunctions;

void main() {
    auto a = new FunctorTest!int(3);
    auto b = fmap(a,(int b) {return b+ 0.5;});
    writefln(to!string(b.a));
}

但是,当您想使用另一个 Functor 实例作为 Type 时,您必须指定 fmap 的所有 4 个类型参数。有没有一种方法只需要指定实例,其他参数就可以从中推导出来?

除了笨拙的 mixin 解决方法之外,还有其他选择吗?

这种方法还有其他我没有看到的缺点吗?

那其他方法呢?

感谢您阅读本文并花时间思考和回答:)


Edit:

是否可以使用 D 中的单元测试来定义像函子法则这样的约束?那肯定很不错。


template genericfunctions() {
  T TestMonoid(T,N = Monoid!T)(T a) {
    return N.mappend(N.mzero(),a);
  }
}

不需要这样:

T TestMonoid(T,N = Monoid!T)(T a) {
  return N.mappend(N.mzero(),a);
}

那应该足够了。有了这个,就不需要mixin either.

是否可以定义约束 就像单元测试中的函子法则 D?

不完全确定我理解您的要求,但您可以使用模板函数/类定义约束:

void isEven(T)(T x) if (isIntegral!T) { return x % 2 == 0; }

该模板只会在以下情况下实例化:T是一个整型。

请参阅底部的“模板约束”部分模板 http://d-programming-language.org/template.html page.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

D 中的特征可以用于类型类吗? 的相关文章

  • 为什么Racket中foldl的定义方式很奇怪?

    在 Haskell 中 与许多其他函数式语言一样 函数foldl被定义为 例如 foldl 0 1 2 3 4 10 这没关系 因为foldl 0 1 2 3 4 根据定义 0 1 2 3 4 但是 在 球拍 中 foldl 0 1 2 3
  • Haskell 对于 Web 应用程序来说足够成熟吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用fold_left/right反转OCaml中的列表

    更新 解决方案 感谢 jacobm 的帮助 我想出了一个解决方案 Folding Recursion let reverse list 3 theList List fold left fun element recursive call
  • 数量重新分配逻辑 - 具有外部数据集的 MapGroups

    我正在研究一种复杂的逻辑 需要将数量从一个数据集重新分配到另一个数据集 在例子中我们有Owner and Invoice 我们需要从数量中减去Invoice准确地Owner匹配 在给定汽车的给定邮政编码处 减去的数量需要重新分配回同一辆车出
  • Haskell:对 Num 类型类的使用感到困惑

    我很困惑为什么这有效 f Num a gt a gt a f x x 42 但这并没有 g Num a gt a gt a g x x 4 2 我本来就明白Num包含实现运算符的所有类型 因此 如果42 is an Int and 4 2
  • 忽略 Racket 中的多个返回值

    在 Racket 中 可以通过执行以下操作从函数返回多个值 define foo values 1 2 3 然后我们可以通过这样做来绑定它们 define values one two three foo Now one一定会1 two t
  • 基于函数签名的模式匹配

    在 F 中 您可以对函数签名进行模式匹配 我想用一个函数来装饰多个函数 该函数测量函数的执行情况并调用 statsd 我当前的功能是 let WrapFunctionWithPrefix metrics Metric Client IRec
  • 返回带有参数的函数的函数

    创建一个应返回包含原始函数参数的函数时 我应该如何处理 例如考虑这个函数 a lt function value function x x value 我希望它返回我在结果函数的参数中指定的值 如下所示 b lt a 3 gt b gt f
  • 如何使用 FS2 中的分类器函数对对象进行分组?

    我有一个无序的流measurements 我想将其分组为固定大小的批次 以便以后可以有效地保留它们 val measurements for id lt Seq foo bar baz value lt 1 to 5 yield id va
  • 如何使用 rxpy/rxjs 延迟事件发射?

    我有两个事件流 一个来自电感环路 另一个来自网络摄像机 汽车将驶过环路 然后撞上相机 如果事件彼此相差在 N 毫秒内 汽车总是会首先进入循环 我想将它们组合起来 但我也希望每个流中不匹配的事件 硬件可能会失败 全部合并到单个流中 像这样的事
  • 在 D 中执行“指向非 const 的 const 指针”的正确方法?

    好的 根据http dlang org const faq html head const http dlang org const faq html head const在 D 中没有办法有一个指向非 const 的 const 指针 但
  • 检查对象是否是字符串列表的列表?

    是什么elegant检查对象是否是字符串列表列表的方法 没有嵌套循环 也许这里必须是构造结构化迭代的常规方法 UPD 像这样的东西 l a b c d 1 3 e 2 f def recurse iterable levels result
  • D 是否足够强大来满足这些功能?

    很长一段时间以来 我一直想设计一种将可扩展性与效率 以及安全性 易用性等 结合起来的编程语言 最近我重新发现了 D 我想知道 D 2 0 是否正是我想要自己打造的语言 我最喜欢的是元编程的潜力 理论上 D可以吗traits http dla
  • 副作用是纯函数中找不到的一切吗?

    可以肯定地说 以下二分法成立 每个给定的函数是 要么纯粹 或有副作用 如果是这样 函数的 副作用就是纯函数中找不到的任何东西 这很大程度上取决于您选择的定义 可以公平地说 函数是pure or impure 纯函数始终返回相同的结果并且不会
  • 函数式编程是否避免了状态?

    根据维基百科 http en wikipedia org wiki Functional programming 函数式编程是一种编程范式 它将计算视为数学函数的评估避免状态和可变数据 强调我的 这是真的吗 我个人的理解是 它使状态更加明确
  • 如何在 Haskell 中枚举递归数据类型?

    这篇博文 http lukepalmer wordpress com 2008 05 02 enumerating a context free language 对于如何使用 Omega monad 对角枚举任意语法有一个有趣的解释 他提
  • 如何在 Objective-C 中编写 lambda 方法?

    如何在 Objective C 中编写 lambda 方法 Objective C 中 lambda 的概念现在封装为Blocks http developer apple com mac library documentation Coc
  • 如何在不进行尾调用优化的情况下用函数式编程替代方案替换 while 循环?

    我正在 JavaScript 中尝试一种更实用的风格 因此 我用诸如map和reduce之类的实用函数替换了for循环 然而 我还没有找到 while 循环的功能替代品 因为尾部调用优化通常不适用于 JavaScript 据我了解 ES6
  • 为什么解析器组合器“seq”用“bind”和“return”定义?

    我正在读这个article http eprints nottingham ac uk 237 1 monparsing pdf关于解析器组合器并且不理解以下内容 他们说使用seq 见下文 导致解析器将嵌套元组作为结果 操作起来很混乱 se
  • 将类型传递给通用 Swift 扩展,或者理想情况下推断它

    说你有 class Fancy UIView 你想找到所有兄弟姐妹Fancy意见 没问题 https stackoverflow com q 37232743 294884 for v UIView in superview subview

随机推荐