标签: parametric-polymorphism

编译器无法识别函数重载,因为类型被擦除.怎么克服这个?

我有一个问题,下面的代码中名为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" …

scala parametric-polymorphism

5
推荐指数
1
解决办法
187
查看次数

为什么这个功能无法进行类型检查?

在关于函数式编程的讲座中,我们看到了以下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 …

polymorphism haskell parametric-polymorphism

5
推荐指数
1
解决办法
330
查看次数

为什么这个实现无效?

假设我有以下类型签名:

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对这个实现感到不安?

这个错误很明显:

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
Run Code Online (Sandbox Code Playgroud)

我想我不明白的是它要求"forall" b.使用这个函数的任何代码都应该只依赖于b一个实例Eq,对吧?在我看来,实现确实符合签名.我的实施怎么样打破了这个签名的期望?

haskell types compiler-errors typeclass parametric-polymorphism

5
推荐指数
1
解决办法
93
查看次数

将多态函数应用于两种不同类型的输入

考虑这个功能:

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)

haskell types parametric-polymorphism

5
推荐指数
1
解决办法
113
查看次数

为什么"TypeToken Collections"被认为是Typesafe?(有效的Java#29)

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

4
推荐指数
1
解决办法
258
查看次数

多态性的等级和(非)预测性之间有什么关系?

多态性的等级和(非)预测性之间有什么关系?

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 函数,它具有类型

forall a. [a] × [a] -> [a]
Run Code Online (Sandbox Code Playgroud)

为了将此函数应用于一对列表,必须用类型替换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

4
推荐指数
1
解决办法
397
查看次数

使用捕获的类型来键入类的属性

我已经按照 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)

metaprogramming parametric-polymorphism raku

4
推荐指数
1
解决办法
99
查看次数

为什么除非我使用临时变量,否则我不能推入 dyn Trait 的 Vec?

这是我的代码:

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

4
推荐指数
1
解决办法
656
查看次数

如何制作为参数类型字段创建默认值的构造函数

对于具有参数类型字段的类型,例如:

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

4
推荐指数
1
解决办法
51
查看次数

Haskell 中的多态性

我是 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)

polymorphism haskell types ghci parametric-polymorphism

4
推荐指数
2
解决办法
114
查看次数