似乎Frege关于类型类的想法与Haskell有很大不同。特别是:
语法似乎不同,原因并不明显。
函数类型不能包含类实例。 (似乎是一个相当奇怪的规则......)
语言规范说明了在子类实例声明中实现超类。 (但是如果你有钻石继承那就不行了......这不会是一个错误,但它不能保证以某种方式工作?)
弗雷格对实例的看法不那么挑剔。 (类型别名是允许的,类型变量不需要是不同的,等等。)
方法可以声明为native
,但不完全清楚这是什么意思。
您似乎可以编写type.method
来访问方法。同样,没有迹象表明这意味着什么或为什么它有用。
子类声明可以为超类方法提供默认实现。 (?)
简而言之,如果知道这些东西的人可以写出这些东西如何运作的解释将是有用的。它列在语言规范中,但描述有点简洁。
(关于语法:我认为Haskell的实例语法更合乎逻辑。“如果X是Y和Z的实例,那么它也是以下列方式的Q实例......”Haskell的类语法似乎总是如此对我来说有点奇怪。如果X实现Eq
,暗示它实现Ord
,则意味着可以实现{{} 1}}如果它想。我不确定什么是更好的符号...)
Per Ingo的回答:
例如,假设Ord
是Foo
的超类。假设每个类有三种方法(Bar
,foo1
,foo2
,foo3
,bar1
,bar2
)和bar3
提供Bar
的默认实现。这应该意味着
instance Bar FB where foo2 = ... foo3 = ... bar1 = ... bar2 = ... bar3 = ...
应该有效。但这会奏效:
instance Foo FB where foo2 = ... foo3 = ... instance Bar FB where bar1 = ... bar2 = ... bar3 = ...
foo1
,那么只为该方法设置默认实现?所以,如果我做了像
这样的事情class Foobar f where foo :: f -> Int native foo bar :: f -> String native bar
那么这只是意味着如果我为某个Java本机类编写一个空实例声明,那么native
会映射到Java中的foo
吗?
特别是,如果一个类方法被声明为object.foo()
,如果我选择的话,我仍然可以为它提供一些其他实现吗?
答案 0 :(得分:6)
您似乎非常仔细地阅读了语言规范。大。但是,不,类型类/实例与Haskell 2010没有实质性的区别。只是一点点,这一点是符号。
你的观点:
ad 1.是的。规则是约束(如果有)附加到类型,类名跟在关键字之后。但是,当将多个param类型类添加到语言中时,这将很快改变,以支持Haskell语法。
ad 2.同时,完全支持功能类型。这将包含在下一个版本中。但是,当前版本仅支持(a-> b)。
ad 3.是的。考虑我们的分类类层次结构Functor - >应用 - >单子。您可以编写以下内容而不是3个单独的实例:
instance Monad Foo where
-- implementation of all methods that are due Monad, Applicative, Functor
ad 4.是的,目前。但是,多参数类型类会有变化。 lang规范建议遵守Haskell 2010规则。
ad 5.如果您使用类型类建模Java类层次结构,则需要使用它。本机函数声明对类型类/实例没什么特别之处。因为您可以在类中具有注释和默认实现(就像在Haskell 2010中一样),您可以以本机声明的形式获得它,其中a)类型和b)实现(通过引用Java方法)。
ad 6.这是正交性的。正如您可以编写M.foo,其中M是一个模块,当T是一个类型(构造函数)时,您可以编写T.foo,因为它们都是名称空间。此外,如果您有“记录”,则当Frege无法推断T.f 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.是的,例如,Ord在比较方面有(==)的默认实现。因此,您可以在不实现(==)的情况下创建某个Ord实例。
希望这会有所帮助。通常,必须说,lang规范需要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,我仍然可以 如果我选择的话,为它提供一些其他实现吗?
当然,就像使用任何其他默认类方法一样。假设使用模式保护实现默认类方法,这并不意味着您必须使用模式保护来实现。
看,
native [pure] foo "javaspec" :: a -> b -> c
只是意味着:请让我成为一个带有a - >类型的frege函数foo
b - > c碰巧使用 javaspec 来实现。 (在语言参考的第6章中应该如何描述。它还没有完成。抱歉。)
例如:
native pure int2long "(long)" :: Int -> Long
编译器将看到这在语法上是一个强制转换操作,当它看到:
... int2long val ...
它将生成如下代码:
((long)(unbox(val))
除此之外,它还将制作一个包装器,以便您可以,例如:
map int2long [1,2,4]
关键是,如果我告诉你:有一个函数X.Y.z,你无法在不查看源代码的情况下判断这是本机还是常规函数。因此,native
是将Java方法,运算符等提升到Frege领域的方法。实际上,Haskell中所谓的“primOp”只是Frege中的一个本机函数。例如,
pure native + :: Int -> Int -> Int
(当然,这并不总是那么容易。)
每个类型[构造函数]都是命名空间。我知道那是怎么回事 有助于臭名昭着的命名字段问题。我不确定你为什么这么做 想在这个命名空间的范围内声明其他东西...
它为您提供了有关顶级命名空间的更多控制权。除此之外,你不必必须定义其他东西。一旦我致力于解决记录领域问题的简单方法,我就没有理由禁止它。