简体   繁体   English

Frege课程如何运作?

[英]How do Frege classes work?

It seems that Frege's ideas about type-classes differ significantly from Haskell. 弗雷格关于类型类的想法似乎与哈斯克尔有很大不同。 In particular: 特别是:

  • The syntax appears to be different, for no obvious reason. 没有明显的原因,语法似乎有所不同。

  • Function types cannot have class instances. 函数类型不能具有类实例。 (Seems a rather odd rule...) (似乎是一个相当奇怪的规则...)

  • The language spec says something about implementing superclasses in a subclass instance declaration. 语言规范说明了有关在子类实例声明中实现超类的内容。 (But not if you have diamond inheritance... it won't be an error, but it's not guaranteed to work somehow?) (但是如果您拥有钻石继承权,那不是。。。这不会是一个错误,但是不能保证它能以某种方式起作用吗?)

  • Frege is less fussy about what an instance looks like. 弗雷格对实例的外观不太挑剔。 (Type aliases are allowed, type variables are not required to be distinct, etc.) (允许使用类型别名,不要求类型变量是唯一的,等等。)

  • Methods can be declared as native , though it is not completely clear what the meaning of this is. 可以将方法声明为native ,尽管尚不清楚其含义是什么。

  • It appears that you can write type.method to access a method. 看来您可以编写type.method来访问方法。 Again, no indication as to what this means or why it's useful. 同样,没有迹象表明这意味着什么或为什么有用。

  • Subclass declarations can provide default implementations for superclass methods. 子类声明可以为超类方法提供默认实现。 (?) (?)

In short, it would be useful if somebody who knows about this stuff could write an explanation of how this stuff works. 简而言之,如果知道这些东西的人可以写一篇关于这个东西如何工作的解释,将很有用。 It's listed in the language spec, but the descriptions are a little bit terse. 它已在语言规范中列出,但说明有些简洁。

(Regarding the syntax: I think Haskell's instance syntax is more logical. "If X is an instance of Y and Z, then it is also an instance of Q in the following way..." Haskell's class syntax has always seemed a bit strange to me. If X implements Eq , that does not imply that it implements Ord , it implies that it could implement Ord if it wants to. I'm not sure what a better symbol would be though...) (关于语法:我认为Haskell的实例语法更合乎逻辑。“如果X是Y和Z的实例,那么它在以下情况下也是Q的实例...” Haskell的类语法始终看起来有点奇怪对我来说。如果X实现Eq ,并不意味着它实现Ord ,这意味着它可以根据需要实现Ord 。我不确定这是什么更好的符号...)


Per Ingo's answer: 根据Ingo的回答:

  • I'm assuming that providing a default implementation for a superclass method only works if you declare your instances "all at once"? 我假设为超类方法提供默认实现仅在您声明实例“一次”的情况下有效吗?

For example, suppose Foo is a superclass of Bar . 例如,假设FooBar的超类。 Suppose each class has three methods ( foo1 , foo2 , foo3 , bar1 , bar2 , bar3 ), and Bar provides a default implementation for foo1 . 假设每个类都有三个方法( foo1foo2foo3bar1bar2bar3 ),并且Barfoo1提供了默认实现。 That should mean that 那应该意味着

instance Bar FB where
  foo2 = ...
  foo3 = ...
  bar1 = ...
  bar2 = ...
  bar3 = ...

should work. 应该管用。 But would this work: 但这会工作:

instance Foo FB where
  foo2 = ...
  foo3 = ...

instance Bar FB where
  bar1 = ...
  bar2 = ...
  bar3 = ...
  • So if I declare a method as native in a class declaration, that just sets the default implementation for that method? 因此,如果我在类声明中将方法声明为native方法,那么该方法只是设置该方法的默认实现?

So if I do something like 所以如果我做类似的事情

class Foobar f where
  foo :: f -> Int
  native foo

  bar :: f -> String
  native bar

then that just means that if I write an empty instance declaration for some Java native class, then foo maps to object.foo() in Java? 那就意味着如果我为某个Java本机类编写一个空实例声明,那么foo映射到Java中的object.foo()

In particular, if a class method is declared as native , I can still provide some other implementation for it if I choose to? 特别是,如果将类方法声明为native ,那么我仍然可以选择提供其他实现方式?

  • Every type [constructor] is a namespace. 每个类型[构造函数]都是一个名称空间。 I get how that would be helpful for the infamous named fields problem. 我知道如何解决臭名昭著的命名字段问题。 I'm not sure why you'd want to declare other things in the scope of this namespace... 我不确定为什么要在此命名空间的范围内声明其他内容...

You seem to have read the language spec very carefully. 您似乎已经非常仔细地阅读了语言规范。 Great. 大。 But, no, type classes/instances do not differ substantially from Haskell 2010. Just a bit, and that bit is notational. 但是,没有,类型类/实例与Haskell 2010并没有实质性的区别。只是一点点,而那一点是符号上的。

Your points: 您的观点:

ad 1. Yes. 广告1.是。 The rule is that the constraints, if any, are attached to the type and the class name follows the keyword. 规则是约束(如果有)附加到类型上,并且类名紧随关键字之后。 But this will change soon in favor of the Haskell syntax when multi param type classes are added to the language. 但是,当在语言中添加多参数类型类时,这将很快改变,以支持Haskell语法。

ad 2. Meanwhile, function types are fully supported. 广告2.同时,完全支持功能类型。 This will be included in the next release. 这将包含在下一个版本中。 The current release has only support for (a->b), though. 但是,当前版本仅支持(a-> b)。

ad 3. Yes. 广告3.是。 Consider our categoric classes hierarchy Functor -> Applicative -> Monad. 考虑我们的分类类层次结构Functor-> Applicative-> Monad。 You can just write the following instead of 3 separate instances: 您只需编写以下内容即可代替3个单独的实例:

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

ad 4. Yes, currently. 广告4.是,当前。 There will be changes with multi param type classes, however. 但是,多参数类型类将有所变化。 The lang spec recommends to stay with the Haskell 2010 rules. lang规范建议遵循Haskell 2010规则。

ad 5. You'd need that if you model Java Class Hierarchies with type classes. 广告5.如果您使用类型类对Java类层次结构进行建模,则需要使用该类。 native function declarations are nothing special for type classes/instances. 本地函数声明对于类型类/实例没有什么特别的。 Because you can have an annotation and a default implementation in a class (just as like in Haskell 2010), you can have this in the form of a native declaration, which gives a) the type and b) the implementation (by referring to a Java method). 因为您可以在类中具有批注和默认实现(就像在Haskell 2010中一样),所以可以以本机声明的形式实现,该声明提供a)类型和b)实现(通过引用a) Java方法)。

ad 6. It's orthogonality. 广告6。这是正交性。 Just as you can write M.foo where M is a module, you can write T.foo when T is a type (constructor), because both are namespaces. 正如您可以在M为模块的情况下编写M.foo一样,当T为类型(构造函数)时也可以编写T.foo,因为两者都是名称空间。 In addition, if you have a "record", you may need to write Tf x when Frege cannot infer the type of x . 另外,如果您有“记录”,则在Frege无法推断x的类型时,可能需要写Tf x 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. Yes, for example, Ord has a default implementation for (==) in terms of compare. 广告7。是的,例如,就比较而言,Ord的默认实现是(==)。 Hence you can make an Ord instance of something without implementing (==). 因此,您可以在不实现(==)的情况下创建Ord实例。

Hope this helps. 希望这可以帮助。 Generally, it must be said, the lang spec needs a) completion and b) updates. 通常,必须说,lang规范需要a)完成和b)更新。 If only the day had 36 hours ..... 如果只有一天有36个小时.....

The syntactic issue is also discussed here: https://groups.google.com/forum/?fromgroups#!topic/frege-programming-language/2mCNWMVg5eY 语法问题也在这里讨论: https : //groups.google.com/forum/?fromgroups#!topic/ frege-programming-language/ 2mCNWMVg5eY

---- Second part ------------ - - 第二部分 - - - - - -

Your example would not work, because, if you define instance Foo FB then this must hold, irrespective of other instances and subclasses. 您的示例不起作用,因为,如果定义instance Foo FB则无论其他实例和子类如何,该instance Foo FB必须成立。 The default foo1 method in Bar will be used only if no Foo instance exists. 仅当不存在Foo实例时,才会使用Bar中的默认foo1方法。

then that just means that if I write an empty instance declaration for some Java native class, then foo maps to object.foo() in Java? 那就意味着如果我为某个Java本机类编写一个空实例声明,那么foo映射到Java中的object.foo()?

Yes, but it depends on the native declaration, it doesn't have to be an Java instance method of that java class, it could also be a static method or a method of another class, or just a member access, etc. 是的,但是它取决于本机声明,它不必是该Java类的Java实例方法,也可以是静态方法或其他类的方法,也可以只是成员访问等。

In particular, if a class method is declared as native, I can still provide some other implementation for it if I choose to? 特别是,如果将类方法声明为本机方法,如果我愿意,我仍然可以为其提供其他实现方式?

Sure, just like with any other default class methods. 当然,就像其他任何默认类方法一样。 Say a default class method is implemented using pattern guards, that does not mean that you must use pattern guards for your implementation. 假设使用模式防护实现了默认的类方法,但这并不意味着您必须使用模式防护来实现。

Look, 看,

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

just means: please make me a frege function foo with type a -> b -> c that happens to use javaspec for implementation. 只是意味着:请给我一个类型为a-> b-> c的frege函数foo ,该函数恰巧使用javaspec进行实现。 (How exactly is supposed to be described in Chapter 6 of the language reference. It's not done yet. Sorry.) For example: (应该在语言参考的第6章中确切描述它。尚未完成。对不起。)例如:

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

The compiler will see tat this is syntactically a cast operation, and when it sees: 编译器将看到这在语法上是强制转换操作,并且会看到:

 ... int2long val ... 

it will generate java code like: 它将生成如下的Java代码:

((long)(unbox(val))

Apart from that, it will also make a wrapper, so that you can, for example: 除此之外,它还会包装一个包装,以便您可以例如:

map int2long [1,2,4]

The point is that, if I tell you: there is a function XYz, you're not able to tell whether this is a native or a regular one without looking at the source code. 关键是,如果我告诉你:有一个XYz函数,则不查看源代码就无法分辨出它是本地的还是常规的。 Hence, native is the way to lift Java methods, operators and so forth to the Frege realm. 因此, native是将Java方法,运算符等提升到Frege领域的方法。 Practically everything that is known as "primOp" in Haskell is just a native function in Frege. 实际上,在Haskell中称为“ primOp”的所有内容在Frege中只是本机功能。 For example, 例如,

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

(It's not always that easy, of course.) (当然,这并不总是那么容易。)

Every type [constructor] is a namespace. 每个类型[构造函数]都是一个名称空间。 I get how that would be helpful for the infamous named fields problem. 我知道如何解决臭名昭著的命名字段问题。 I'm not sure why you'd want to declare other things in the scope of this namespace... 我不确定为什么要在此命名空间的范围内声明其他内容...

It gives you somewhat more control regarding the top namespace. 它使您可以更好地控制顶级名称空间。 Apart from that, you don't have to define other things there. 除此之外,您不必在那里定义其他内容。 I just did not see a reason to forbid it once I committed to this simple approach to tackle the record field problem. 一旦我致力于解决记录领域问题的简单方法,我只是没有理由禁止它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM