【问题标题】:How do Frege classes work?弗雷格课程如何运作?
【发布时间】:2012-05-18 19:59:42
【问题描述】:

似乎弗雷格关于类型类的想法与 Haskell 有很大不同。特别是:

  • 语法似乎有所不同,原因不明。

  • 函数类型不能有类实例。 (似乎是一个相当奇怪的规则......)

  • 语言规范说明了在子类实例声明中实现超类。 (但如果你有钻石继承......不会出错,但不能保证以某种方式工作?)

  • Frege 对实例的外观不那么挑剔。 (允许使用类型别名,类型变量不需要不同等)

  • 方法可以声明为native,虽然不完全清楚这是什么意思。

  • 看来您可以写type.method 来访问方法。同样,没有说明这意味着什么或为什么有用。

  • 子类声明可以为超类方法提供默认实现。 (?)

简而言之,如果知道这些东西的人可以写下关于这些东西如何工作的解释,那将会很有用。它在语言规范中列出,但描述有点简洁。

(关于语法:我觉得Haskell的实例语法比较合乎逻辑。“如果X是Y和Z的实例,那么它也是Q的实例,如下方式……” Haskell的类语法一直看起来我有点奇怪。如果 X 实现了Eq,这并不暗示它实现了Ord,这意味着它可以实现Ord到。虽然我不确定什么是更好的符号......)


根据英戈的回答:

  • 我假设为超类方法提供默认实现仅在您“一次性”声明您的实例时才有效?

例如,假设FooBar 的超类。假设每个类都有三个方法(foo1foo2foo3bar1bar2bar3),并且Barfoo1提供了默认实现。这应该意味着

实例吧 FB 在哪里 富二 = ... foo3 = ... 酒吧1 = ... 酒吧2 = ... 酒吧3 = ...

应该可以。但这行得通吗:

实例 Foo FB 在哪里 富二 = ... foo3 = ... 实例吧 FB 在哪里 酒吧1 = ... 酒吧2 = ... 酒吧3 = ...
  • 那么,如果我在类声明中将方法声明为native,那只是为该方法设置默认实现?

所以如果我做类似的事情

类 Foobar f 在哪里 foo :: f -> Int 本地富 bar :: f -> 字符串 本地酒吧

那么这只是意味着如果我为某个 Java 原生类编写了一个空实例声明,那么foo 映射到 Java 中的object.foo()

特别是,如果一个类方法被声明为native,如果我选择,我仍然可以为它提供一些其他实现吗?

  • 每个类型 [构造函数] 都是一个命名空间。我知道这对臭名昭著的命名字段问题有什么帮助。我不确定你为什么要在这个命名空间的范围内声明其他东西......

【问题讨论】:

    标签: class types functional-programming frege


    【解决方案1】:

    您似乎已经非常仔细地阅读了语言规范。伟大的。但是,不,类型类/实例与 Haskell 2010 没有太大区别。只是一点点,那一点是符号。

    您的积分:

    广告 1. 是的。规则是约束(如果有的话)附加到类型上,类名跟在关键字后面。但是当多参数类型类被添加到语言中时,这将很快改变,有利于 Haskell 语法。

    ad 2. 同时全面支持函数类型。这将包含在下一个版本中。不过,当前版本仅支持 (a->b)。

    ad 3. 是的。考虑我们的分类类层次结构 Functor -> Applicative -> Monad。您可以只编写以下内容而不是 3 个单独的实例:

    instance Monad Foo where
        -- implementation of all methods that are due Monad, Applicative, Functor
    

    ad 4. 是的,目前。但是,多参数类型类将会发生变化。语言规范建议遵守 Haskell 2010 规则。

    ad 5. 如果您使用类型类对 Java 类层次结构建模,您将需要它。本机函数声明对于类型类/实例没有什么特别之处。因为你可以在一个类中拥有一个注解和一个默认实现(就像在 Haskell 2010 中一样),你可以以原生声明的形式拥有它,它给出 a)类型和 b)实现(通过引用Java 方法)。

    ad 6. 这是正交性。正如你可以在 M 是一个模块的情况下编写 M.foo 一样,你可以在 T 是一个类型(构造函数)时编写 T.foo,因为两者都是命名空间。另外,如果你有“记录”,当弗雷格无法推断出x的类型时,你可能需要写T.f x

    foo x = x.a + x.b    -- this doesn't work, type of x is unknown
    -- remedy 1: provide a type signature
    foo :: Record -> Int  -- Record being some data type
    -- remedy 2: access the field getter functions directly
    foo x = Record.a x + Record.b x
    

    ad 7. 是的,例如,Ord 在比较方面具有 (==) 的默认实现。因此,您可以在不实现 (==) 的情况下创建某事物的 Ord 实例。

    希望这会有所帮助。一般来说,必须说,语言规范需要 a) 完成和 b) 更新。如果一天只有 36 小时就好了.....

    这里也讨论了句法问题:https://groups.google.com/forum/?fromgroups#!topic/frege-programming-language/2mCNWMVg5eY

    ---- 第二部分------------

    您的示例不起作用,因为如果您定义instance Foo FB,那么无论其他实例和子类如何,它都必须成立。仅当不存在 Foo 实例时才会使用 Bar 中的默认 foo1 方法。

    那么这只是意味着如果我为 一些 Java 原生类,然后 foo 映射到 Java 中的 object.foo()?

    是的,但它取决于本地声明,它不必是该 java 类的 Java 实例方法,也可以是静态方法或另一个类的方法,或者只是成员访问等.

    特别是,如果一个类方法被声明为原生的,我仍然可以 如果我愿意,可以为它提供一些其他的实现吗?

    当然,就像任何其他默认类方法一样。假设默认类方法是使用模式防护实现的,这并不意味着您必须使用模式防护来实现。

    看,

    native [pure] foo "javaspec" :: a -> b -> c
    

    只是意味着:请给我一个 freg 函数foo,其类型为 a -> b -> c,恰好使用 javaspec 来实现。 (具体应该如何在语言参考的第 6 章中描述。还没有完成。对不起。) 例如:

    native pure int2long "(long)" :: Int -> Long
    

    编译器会看到这在语法上是一个强制转换操作,当它看到时:

     ... int2long val ... 
    

    它会生成类似的java代码:

    ((long)(unbox(val))
    

    除此之外,它还会做一个包装器,这样你就可以,例如:

    map int2long [1,2,4]
    

    关键是,如果我告诉你:有一个函数 X.Y.z,如果不查看源代码,你将无法判断它是原生函数还是常规函数。因此,native 是将 Java 方法、运算符等提升到 Frege 领域的方法。实际上,在 Haskell 中称为“primOp”的所有内容都只是 Frege 中的本机函数。例如,

    pure native + :: Int -> Int -> Int
    

    (当然,这并不总是那么容易。)

    每个类型 [constructor] 都是一个命名空间。我知道那会怎样 有助于解决臭名昭著的命名字段问题。我不知道你为什么 想在这个命名空间的范围内声明其他东西...

    它让您对顶级命名空间有更多的控制权。除此之外,您不必必须在此处定义其他内容。一旦我致力于这种简单的方法来解决记录字段问题,我只是没有看到禁止它的理由。

    【讨论】:

    • 我想澄清几点。不过,我认为他们不适合发表评论。所以我将改为编辑问题......
    • @MathematicalOrchid - 当然,没问题。
    • 那么我该去哪里帮助完成规范的编写? ;-)
    • @MathematicalOrchid - 我不确定我能否解析您的问题(请记住,非英语母语人士),但如果您问是否可以做出贡献,不客气。只需在论坛中介绍自己并告诉那里的人您是谁以及您认为自己可以做什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-17
    相关资源
    最近更新 更多