我有一个问题,下面的代码中名为fooSome的两个方法不能编译,因为编译器报告重复的方法名称有问题:
class Foo() {
// variable block has 2 closure variables
def fooSome(block: Some[(Int, String) => Unit]) = {
}
// variable block has 1 closure variables
def fooSome(block: Some[Int => Unit]) = {
}
// variable block has 2 closure variables
def fooNoSome(block: (Int, String) => Unit) = {
}
// variable block has 1 closure variables
def fooNoSome(block: Int => Unit) = {
}
}
Run Code Online (Sandbox Code Playgroud)
相反,编译器报告没有与名为fooNoSome的两个方法发生此类方法名称冲突.所以问题是编译器没有看到"Some [(Int,String)=> Unit]"和"Some [(Int)=> Unit]" 之间的区别,而"(Int,String)=> Unit" …
在关于函数式编程的讲座中,我们看到了以下Haskell函数:
f :: Bool -> Int -> (a -> Int) -> Int
f x y z = if x then y + y else (z x) + (z y)
Run Code Online (Sandbox Code Playgroud)
预计此功能将无法进行类型检查.但是,没有解释这种情况发生的原因.在GHCI中尝试时,我得到以下输出:
Prelude> :l test [1 of 1] Compiling Main ( test.hs,
interpreted )
test.hs:2:35:
Couldn't match expected type `a' with actual type `Bool'
`a' is a rigid type variable bound by
the type signature for f :: Bool -> Int -> (a -> Int) -> Int
at test.hs:1:6
Relevant bindings include … 假设我有以下类型签名:
someFunction :: (Eq a, Eq b) => a -> b
Run Code Online (Sandbox Code Playgroud)
实施:
someFunction x = (2 :: Int)
Run Code Online (Sandbox Code Playgroud)
(不要把它放得太远,这只是一个例子).
我对签名的理解是" someFunction接受一个作为Eq类型类的实例的参数,并返回一个值(可以是不同类型),它是Eq类型类的实例".Int是一个实例Eq,为什么GHC对这个实现感到不安?
这个错误很明显:
Run Code Online (Sandbox Code Playgroud)Couldn't match expected type ‘b’ with actual type ‘Int’ ‘b’ is a rigid type variable bound by the type signature for: someFunction :: forall a b. (Eq a, Eq b) => a -> b
我想我不明白的是它要求"forall" b.使用这个函数的任何代码都应该只依赖于b一个实例Eq,对吧?在我看来,实现确实符合签名.我的实施怎么样打破了这个签名的期望?
haskell types compiler-errors typeclass parametric-polymorphism
考虑这个功能:
doToBoth f x y = (f x, f y)
Run Code Online (Sandbox Code Playgroud)
它在简单的情况下按预期工作:
doToBoth (2 *) 10 15 == (20, 30)
doToBoth head [1,2] [3,4,5] == (1, 3)
Run Code Online (Sandbox Code Playgroud)
然后我尝试了这些:
doToBoth head [1,10,100] "apple"
doToBoth pred 2 'b'
Run Code Online (Sandbox Code Playgroud)
我希望这些都导致(1, 'a'),但它们只会导致类型错误.问题是推断类型doToBoth不够多态:
doToBoth :: (a1 -> a2) -> a1 -> a1 -> (a2, a2)
Run Code Online (Sandbox Code Playgroud)
看到这个,我尝试添加一个显式类型签名来修复它:
doToBoth :: (t ~ (i1 -> o1), t ~ (i2 -> o2)) => t -> i1 -> i2 -> (o1, o2)
Run Code Online (Sandbox Code Playgroud)
这种类型的签名被接受,但它没有解决问题,并检查发生了什么,:t doToBoth发现它最终得到了与原始推断的类型相同的类型:
doToBoth …Run Code Online (Sandbox Code Playgroud) Effective Java中的第29项提供了一种实现"类型安全"异构集合的方法,它基本上归结为这样的东西:
public Class HeterogeneousContainer {
private Map<Class<?>, Object> container = new HashMap<>();
public <T> put(Class<T> type, T instance) {
container.put(type, instance);
}
public <T> T get(Class<T> type) {
//essentially just
// return (T) container.get(type);
return type.cast(container.get(type));
}
}
Run Code Online (Sandbox Code Playgroud)
其中(我推测)就像这样(由制作人)使用:
List<HeterogeneousContainer> resultSet = new ArrayList<>();
...
resultSet.add(new HeterogeneousContainer());
...
resultSet.get(rowIndex).add(Column1.class, column1Value);
resultSet.get(rowIndex).add(Column2.class, column2Value);
...
Run Code Online (Sandbox Code Playgroud)
并且像这样(由消费者):
for(HeterogeneousContainer row:resultSet) {
Column1 column1Value = row.get(Column1.class);
Column2 column2Value = row.get(Column2.class);
...
//do something with the columnValues
}
Run Code Online (Sandbox Code Playgroud)
我现在的问题是为什么这被认为类型安全?这比仅仅将列名放入地图还是只使用常规List/ List<Object>并按索引查找列更好? …
java generics collections type-safety parametric-polymorphism
多态性的等级和(非)预测性之间有什么关系?
1 级多态性可以是谓词还是非谓词?
rank-k 多态性k > 1可以是谓语还是非谓语?
我的困惑来自:
为什么https://en.wikipedia.org/wiki/Parametric_polymorphism提到等级 1 多态性下的预测性?(在我看来,rank-1 意味着可预测性)
Rank-1 (prenex) 多态性
在 prenex 多态系统中,类型变量可能无法用多态类型实例化。 [4] 这与所谓的“ML 风格”或“ Let-多态性”非常相似(从技术上讲,ML 的 Let-多态性还有一些其他语法限制)。这种限制使得多态和非多态类型之间的区别变得非常重要;因此,在谓词系统中,多态类型有时被称为类型模式,以区别于普通(单态)类型,后者有时被称为单类型。结果是所有类型都可以写成将所有量词放在最外面(前缀)位置的形式。例如,考虑上面描述的 append 函数,它具有类型
Run Code Online (Sandbox Code Playgroud)forall a. [a] × [a] -> [a]为了将此函数应用于一对列表,必须用类型替换
a函数类型中的变量,以便参数的类型与结果函数类型相匹配。在非谓语系统中,被替换的类型可以是任何类型,包括本身是多态的类型;因此 append 可以应用于具有任何类型元素的列表对——甚至可以应用于多态函数列表,例如 append 本身。ML 语言中的多态性是预测性的。[需要引用]这是因为预测性以及其他限制使类型系统足够简单,因此始终可以进行完整的类型推断。
作为一个实际示例,OCaml(ML 的后代或方言)执行类型推断并支持不可预测的多态性,但在某些情况下,当使用不可预测的多态性时,系统的类型推断是不完整的,除非程序员提供了一些显式的类型注释。
...
谓词多态性
在谓词参数多态系统中,不能以实例化为多态类型的方式使用
?包含 类型变量的类型??。谓语类型理论包括 Martin-Löf 类型理论和 NuPRL。
https://wiki.haskell.org/Impredicative_types:
谓词类型是多态性的一种高级形式,与 rank-N 类型形成对比。
标准 Haskell 通过使用类型变量允许多态类型,类型变量被理解为普遍量化:
id :: a …
polymorphism haskell programming-languages impredicativetypes parametric-polymorphism
我已经按照 SO 问题如何在 Perl 6 中设置参数化类的答案中的 说明进行操作?. 但是,我遇到了一些软障碍。我正在尝试使用类型捕获键入内部类的属性并收到以下错误:
Died with X::TypeCheck::Assignment
in submethod BUILDALL at ...
in method insert at ...
in block <unit> at ...
Run Code Online (Sandbox Code Playgroud)
在下面的示例中,我输入了 classBinaryNode的$.item属性(with T),但这样做会导致上述错误:
class BinarySearchTree {
my role BTSImpl[::T] {
my class BinaryNode is rw {
has T $.item;
has BinaryNode $.left;
has BinaryNode $.right;
}
method create-node( T $x ) {
BinaryNode.new(item => $x)
}
}
method ^parameterize(Mu:U \this, Mu \T) {
my $type := …Run Code Online (Sandbox Code Playgroud) 这是我的代码:
use std::rc::{Rc, Weak};
use std::cell::RefCell;
trait Trait {}
fn push<E: Trait>(e: E) {
let mut v: Vec<Rc<RefCell<Box<dyn Trait>>>> = Vec::new();
// let x = Rc::new(RefCell::new(Box::new(e)));
// v.push(x); // error
v.push(Rc::new(RefCell::new(Box::new(e)))); // works fine
}
Run Code Online (Sandbox Code Playgroud)
将v.push(x)引发此错误:
error[E0308]: mismatched types
--> src/main.rs:12:12
|
7 | fn push<E: Trait>(e: E) {
| - this type parameter
...
12 | v.push(x);
| ^ expected trait object `dyn Trait`, found type parameter `E`
|
= note: expected struct `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn Trait>>>`
found struct …Run Code Online (Sandbox Code Playgroud) polymorphism traits rust parametric-polymorphism trait-objects
对于具有参数类型字段的类型,例如:
struct Point{T <: AbstractFloat}
x::T
y::T
end
Run Code Online (Sandbox Code Playgroud)
如何制作一个使用所需类型创建默认值的外部构造函数?例如,我想要Point()which 不带任何参数来 create Point{T}(0.0, 0.0),我仍然可以通过某种方式指定TasFloat64或其他类型。
constructor types default-value parametric-polymorphism julia
我是 Haskell 的新手,从第一原则开始阅读 Haskell。
顺便说一句,这个问题一般与本书无关,我以以下问题为例
在第 10 章,第 10.5 节,Q 5,f 部分
题:
以下是与您已经看到的非常相似的简单折叠,但每个折叠都至少有一个错误。请修复它们并在您的 REPL 中测试
f) 文件夹 const 'a' [1..5]
并且它给出了以下错误 No instance for (Num Char)来自文字“1”

只是意味着 1 不能在这里用作 Char
但我在本章中读到折叠就像文本重写器,用函数替换 cons(:) 并用累加器替换空列表,所以结果是(我缩短了列表)
foldr const 'a' [1..2]
to
(1 `const` (2 `const` 'a'))
Run Code Online (Sandbox Code Playgroud)
并且它的工作没有编译器错误
那么有什么问题呢?为什么第一个不工作,它的重写工作?
但我看到重写的形式const有两种形式
Int -> Int -> Int
and
Int -> Char -> Int
Run Code Online (Sandbox Code Playgroud)
也许这是它的BCS所以我固定的类型,const像这样
cont :: Int -> Int -> Int
cont = const
Run Code Online (Sandbox Code Playgroud)
现在当我说使用它时
(1 `cont` (2 `cont` 'a'))
Couldn't …Run Code Online (Sandbox Code Playgroud) haskell ×5
polymorphism ×4
types ×4
collections ×1
constructor ×1
generics ×1
ghci ×1
java ×1
julia ×1
raku ×1
rust ×1
scala ×1
traits ×1
type-safety ×1
typeclass ×1