我正在尝试定义一个结构类型,定义任何具有"add"方法的集合(例如,java集合).使用这个,我想定义一些对某个集合进行操作的高阶函数
object GenericTypes {
type GenericCollection[T] = { def add(value: T): java.lang.Boolean}
}
import GenericTypes._
trait HigherOrderFunctions[T, CollectionType[X] <: GenericCollection[X]] {
def map[V](fn: (T) => V): CollectionType[V]
....
}
class RichJList[T](list: List[T]) extends HigherOrderFunctions[T, java.util.List]
Run Code Online (Sandbox Code Playgroud)
这不会编译与以下错误
error: Parameter type in structural refinement may not refer to abstract type defined outside that same refinement
Run Code Online (Sandbox Code Playgroud)
我尝试删除GenericCollection上的参数并将其放在方法上:
object GenericTypes {
type GenericCollection = { def add[T](value: T): java.lang.Boolean}
}
import GenericTypes._
trait HigherOrderFunctions[T, CollectionType[X] <: GenericCollection]
class RichJList[T](list: List[T]) extends HigherOrderFunctions[T, java.util.List]
Run Code Online (Sandbox Code Playgroud)
但我得到另一个错误: …
在观看了Rich Hickey对Clojure 1.2 协议的采访,并且对Clojure知之甚少之后,我对Clojure协议提出了一些问题:
在研究结构类型时,我发现以下帖子描述了Go中的接口如何在运行时转换为方法查找表.帖子中描述的过程似乎与 Scala的可选结构类型系统和Java语言的White Oak扩展所描述的反射和生成技术大不相同.
是否有任何深入的资源讨论如何在OCaml中实现结构类型?我对任何有关标称类型系统的优化或运行时性能比较的讨论特别感兴趣.
我听说Haskell被描述为具有结构类型.据我了解,记录是一个例外.例如foo,HRec2即使在某些类型的东西中也不能调用它们,HRec并且HRec2在它们的字段中只是名义上不同.
data HRec = HRec { x :: Int, y :: Bool }
data HRec2 = HRec2 { p :: Int, q :: Bool }
foo :: HRec -> Bool
Run Code Online (Sandbox Code Playgroud)
是否有一些解释拒绝将结构类型扩展到包括记录在内的所有内容?
是否存在结构类型的静态类型语言,即使是记录?对于所有静态类型语言,我可以阅读一下这个问题吗?
我正在尝试编写一个泛型interpolate方法,该方法适用于任何具有两种方法的类型,a *和a +,如下所示:
trait Container {
type V = {
def *(t: Double): V
def +(v: V): V
}
def interpolate(t: Double, a: V, b: V): V = a * (1.0 - t) + b * t
}
Run Code Online (Sandbox Code Playgroud)
这不起作用(在Scala 2.8.0.RC7上),我收到以下错误消息:
<console>:8: error: recursive method + needs result type
def +(v: V): V
^
<console>:7: error: recursive method * needs result type
def *(t: Double): V
^
Run Code Online (Sandbox Code Playgroud)
如何正确指定结构类型?(或者有更好的方法吗?)
有时我们有几个类具有相同签名的某些方法,但是它们与声明的Java接口不对应.例如,两者JTextField和JButton(在其他几个中 javax.swing.*)都有一种方法
public void addActionListener(ActionListener l)
Run Code Online (Sandbox Code Playgroud)
现在,假设我希望对具有该方法的对象执行某些操作; 那么,我想要一个界面(或者自己定义它),例如
public interface CanAddActionListener {
public void addActionListener(ActionListener l);
}
Run Code Online (Sandbox Code Playgroud)
所以我可以写:
public void myMethod(CanAddActionListener aaa, ActionListener li) {
aaa.addActionListener(li);
....
Run Code Online (Sandbox Code Playgroud)
但是,遗憾的是,我不能:
JButton button;
ActionListener li;
...
this.myMethod((CanAddActionListener)button,li);
Run Code Online (Sandbox Code Playgroud)
这个演员是非法的.编译器知道它JButton 不是 a CanAddActionListener,因为类没有声明实现该接口...... 但是它"实际"实现了它.
这有时会带来不便 - 而Java本身已经修改了几个核心类来实现由旧方法构成的新接口(String implements CharSequence例如).
我的问题是:为什么会这样?我理解声明一个类实现接口的实用程序.但无论如何,看看我的例子,为什么编译器不能推断出类JButton"满足"接口声明(查看它内部)并接受转换?这是编译器效率的问题还是存在更多基本问题?
我对答案的总结:这是一个Java可以允许一些"结构类型"(一种鸭子打字 - 但在编译时检查)的情况.它没有.除了一些(对我来说不清楚)性能和实现困难之外,还有一个更为基本的概念:在Java中,接口的声明(以及一般来说,所有内容)并不仅仅是结构性的(具有方法)这些签名)但语义:这些方法应该实现一些特定的行为/意图.因此,一个在结构上满足某些接口的类(即,它具有所需签名的方法)并不一定在语义上满足它(一个极端的例子:回想一下"标记接口",它甚至没有方法!).因此,Java可以断言一个类实现了一个接口,因为(并且只是因为)已经显式声明了它.其他语言(Go,Scala)有其他语言.
我们可以val s: String从函数外部获得使用反射的类型f吗?
val f = (r: {val s: String}) => {
}
Run Code Online (Sandbox Code Playgroud) 一点背景,我基本上需要定义一个int包装类型,比如说MyInt(在其他一些类中),以及另一个Interval可以接受MyInt对象以及其他类型对象的泛型类型.由于不可接受的类型Interval不属于整洁的层次结构,我认为这将是实验的完美用例Protocol,在我的情况下需要几个方法和几个@classmethods.所有方法都返回一个"自我类型",即MyInt.my_method返回一个MyInt.这是一个MCVE:
from dataclasses import dataclass
from typing import Union, ClassVar, TypeVar, Generic, Type
from typing_extensions import Protocol
_P = TypeVar('_P', bound='PType')
class PType(Protocol):
@classmethod
def maximum_type_value(cls: Type[_P]) -> _P:
...
@classmethod
def minimum_type_value(cls: Type[_P]) -> _P:
...
def predecessor(self: _P) -> _P:
...
def successor(self: _P) -> _P:
...
@dataclass
class MyInteger:
value: int
_MAX: ClassVar[int] = 42
_MIN: ClassVar[int] = -42 …Run Code Online (Sandbox Code Playgroud) 我们有一个以下示例:
public class X { }
public class Y { }
public class Z { }
public delegate IDictionary<Y, IList<Z>> Bar(IList<X> x, int i);
public interface IFoo
{
// ...
Bar Bar { get; }
}
public class Foo : IFoo
{
// ...
public Bar Bar
{
get
{
return null; //...
}
}
}
void Main()
{
IFoo foo; //= ...
IEnumerable<IList<X>> source; //= ...
var results = source.Select(foo.Bar); // <- compile error here
}
Run Code Online (Sandbox Code Playgroud)
编译器说:
无法从用法推断出方法'System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable,System.Func)'的类型参数.尝试显式指定类型参数.
这是因为它无法转换 …
说我有以下代码:
class Bar { def bar(b:Bar):Boolean = true }
def func(b:Bar) = b.bar(b)
Run Code Online (Sandbox Code Playgroud)
以上工作正常.该类Bar在第三方库中定义,并且有几个类似的类,每个类都有一个bar方法
class Foo { def bar(f:Foo):Boolean = false }
Run Code Online (Sandbox Code Playgroud)
func我想要定义func使用泛型类型B ,而不是为每个这样的类编写,只要它有一个bar正确签名的方法.
我尝试了以下但它给了我一个错误:
def func[B <: {def bar(a:B):Boolean}](b:B) = b.bar(b) // gives error
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
<console>:16: error: Parameter type in structural refinement may not refer to
an abstract type defined outside that refinement
def func[B <: {def bar(a:B):Boolean}](b:B) = b.bar(b)
^
Run Code Online (Sandbox Code Playgroud)
但是,如果我执行以下操作,方法定义仍然有效,但调用会产生错误:
def func[B <: {def bar(a:Any):Boolean}](b:B) = b.bar(b) …Run Code Online (Sandbox Code Playgroud) scala ×6
alias ×1
c# ×1
class-method ×1
clojure ×1
delegates ×1
duck-typing ×1
generics ×1
go ×1
haskell ×1
interface ×1
java ×1
mypy ×1
ocaml ×1
protocols ×1
python ×1
python-3.x ×1
record ×1
reflection ×1
types ×1