问题标签 [higher-order-types]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
java - “泛型”和“高阶类型”之间有什么关系?
来自这个问题:Scala 中的高级类型是什么?,我明白什么是higher-order types
(也first-order type
和proper type
)。
但是还有一个问题:generics
和“高阶类型”有什么关系?
我知道 Java 支持generics
,这就像first-order
Scala 中的类型。
以下哪项是正确的?
- 在 Scala 中,只有
first-order type
isgenerics
- 在 Scala 中,
first-order
类型higher-order
都属于generics
- 在Java中,
generics
只是平均first-order
类型,它不完整 generics
first-order
是一个通用术语,意味着我们可以对类型进行“抽象” ,无论是higher-order
f# - 在 F# 中使用对象代数模拟更高种类的多态性
在论文Streams à la carte: Extensible Pipelines with
Object Algebras
Biboudis 等人。概述使用对象代数“模拟类型构造器多态性”的方法。
我正在尝试使用此方法在 F# 中实现一个高阶示例,类似于 中描述的示例,Typed Tagless Final Interpreters
并具有以下内容:
相关部分Brand Freshness
描述了在类型构造函数中嵌套类。我对 F# 的翻译如下:
但是,我得到了错误The type 't' is not defined
。
在 F# 中写这个的正确方法是什么?
haskell - 可以在类型级别上对函数进行模式匹配,但在值级别上却不行,为什么会有这种差异?
在SPJ 的这篇论文的第 3 页和第 4 页中,写道:
和:
类声明现在引入了类型函数 Ref(具有指定的种类)以及通常的值函数,例如 newRef(每个都具有指定的类型)。类似地,每个实例声明都提供了一个子句,该子句定义实例类型的类型函数以及每个值函数的见证。
我们说 Ref 是一个类型族,或类 Mutation 的关联类型。它的行为类似于 类型级别的函数,因此我们也将 Ref 称为类型函数。应用类型函数使用与应用类型构造函数相同的语法:上面的 Ref ma 表示将类型函数 Ref 应用于 m,然后将生成的类型构造函数应用于 a。
所以,换句话说,
Ref :: (*->*)->*->*
也就是说,Ref
将类型级别函数作为参数,如Maybe
or IO
or[]
并生成另一个类型级别函数,例如IORef
使用模式匹配,即Ref
由模式匹配定义。
那么,怎么可能在类型级别而不是值级别上对函数进行模式匹配呢?
例如,
不可能写,因为函数的相等性是不可判定的。
1)那么在类型级别上这怎么可能没有问题呢?
2)是因为类型级别的功能非常有限吗?因此,类型级别上的任何类型的函数都不能作为参数Ref
,只有少数选择,即程序员声明的函数,而不是像 (+) 这样的函数,它们比程序员声明的函数更通用?这就是类型级别函数模式匹配没有问题的原因吗?
3) 这个问题的答案是否与GHC 规范的这一部分有关?
java - 为什么 Java 中不能声明 Monad 接口?
在你开始阅读之前:这个问题不是关于理解 monad,而是关于识别 Java 类型系统的限制,它阻止了Monad
接口的声明。
在我努力理解 monad 的过程中,我阅读了 Eric Lippert 的这个SO-answer 关于一个关于 monad 的简单解释的问题。在那里,他还列出了可以在 monad 上执行的操作:
- 有一种方法可以获取未放大类型的值并将其转换为放大类型的值。
- 有一种方法可以将未放大类型的操作转换为放大类型的操作,该操作遵循前面提到的函数组合规则
- 通常有一种方法可以将未放大的类型从放大的类型中恢复出来。(最后一点对于 monad 不是绝对必要的,但经常存在这样的操作。)
在阅读了有关 monad 的更多信息后,我将第一个操作确定为return
函数,将第二个操作确定为bind
函数。我找不到第三个操作的常用名称,所以我将它称为unbox
函数。
为了更好地理解 monad,我继续尝试Monad
在 Java 中声明一个泛型接口。为此,我首先查看了上面三个函数的签名。对于 Monad M
,它看起来像这样:
该return
函数不在 的实例上执行M
,因此它不属于Monad
接口。相反,它将被实现为构造函数或工厂方法。
同样,现在,我从接口声明中省略了该unbox
函数,因为它不是必需的。对于接口的不同实现,这个函数会有不同的实现。
因此,Monad
接口只包含bind
功能。
让我们尝试声明接口:
有两个缺陷:
- 该
bind
函数应该返回具体的实现,但是它只返回接口类型。这是一个问题,因为我们在具体子类型上声明了拆箱操作。我将此称为问题 1。 - 该
bind
函数应该检索一个函数作为参数。我们稍后会解决这个问题。
在接口声明中使用具体类型
这解决了问题 1:如果我对 monad 的理解是正确的,那么该bind
函数总是返回一个与调用它的 monad 具有相同具体类型的新 monad。因此,如果我有一个Monad
名为 的接口的实现M
,那么M.bind
将返回另一个M
但不返回Monad
. 我可以使用泛型来实现它:
起初,这似乎可行,但至少有两个缺陷:
一旦实现类不提供自己而是提供
Monad
接口的另一个实现作为类型参数,这就会崩溃M
,因为这样该bind
方法将返回错误的类型。例如将返回一个实例
MonadImpl
,它应该返回一个FaultyMonad
. 但是,我们可以在文档中指定此限制,并将此类实现视为程序员错误。第二个缺陷更难解决。我将其称为问题 2:当我尝试实例化类时,
MonadImpl
我需要提供M
. 让我们试试这个:要获得有效的类型声明,这必须无限进行。这是另一个尝试:
虽然这似乎可行,但我们只是将问题推迟到被调用方。这是该功能对我有用的唯一用法:
这基本上归结为
但这显然不是我们想要的。
在自己的声明中使用带有移位类型参数的类型
现在,让我们将函数参数添加到bind
函数中: 如上所述,bind
函数的签名如下所示:T1 -> M<T2>
. 在 Java 中,这是类型Function<T1, M<T2>>
。这是第一次尝试用参数声明接口:
我们必须将类型T1
作为泛型类型参数添加到接口声明中,以便我们可以在函数签名中使用它。第一个?
是T1
返回的 monad 类型M
。要将其替换为T2
,我们必须将T2
其自身添加为泛型类型参数:
现在,我们遇到了另一个问题。我们在接口中添加了第三个类型参数Monad
,所以我们必须添加一个新?
的来使用它。我们将暂时忽略新?
的,而首先研究现在?
。它是M
返回的 monad 类型M
。让我们尝试?
通过重命名并引入另一个M
来删除它:M1
M2
引入另一个T3
结果:
并引入另一个M3
结果:
我们看到,如果我们尝试解决所有问题,这将永远持续下去?
。这是问题 3。
总结一下
我们发现了三个问题:
- 在抽象类型的声明中使用具体类型。
- 实例化一个接收自身作为泛型类型参数的类型。
- 声明一个在其声明中使用自身的类型,并带有移位的类型参数。
问题是:Java 类型系统中缺少什么特性?由于有些语言可以使用 monad,因此这些语言必须以某种方式声明Monad
类型。这些其他语言如何声明Monad
类型?我无法找到有关此的信息。我只找到有关具体单子声明的信息,例如Maybe
单子。
我错过了什么吗?我可以用 Java 类型系统正确解决这些问题之一吗?如果我不能用 Java 类型系统解决问题 2,那么 Java 没有警告我关于不可实例化类型声明的原因是什么?
如前所述,这个问题与理解单子无关。如果我对 monads 的理解是错误的,你可能会给出提示,但不要试图给出解释。如果我对单子的理解是错误的,那么所描述的问题仍然存在。
这个问题也不是关于是否可以Monad
在 Java 中声明接口。这个问题已经得到了 Eric Lippert 在上面链接的 SO-answer 中的回答:不是。这个问题是关于阻止我这样做的究竟是什么限制。Eric Lippert 将此称为高级类型,但我无法理解它们。
大多数 OOP 语言没有足够丰富的类型系统来直接表示 monad 模式本身;您需要一个支持比泛型类型更高的类型的类型系统。所以我不会尝试那样做。相反,我将实现表示每个 monad 的泛型类型,并实现表示您需要的三个操作的方法:将值转换为放大值,将放大值转换为值,以及将未放大值上的函数转换为放大的值。
type-systems - 高阶类型与高阶类型的消歧
在上一个问题中,我问为什么不能在 Java 中声明 Monad 接口?. 在那里,我收到了 Brian Goetz 的评论,说我应该将“高阶类型”称为“高阶类型”。
现在,我阅读了更多关于类型系统的内容,并且理解了更高种类的类型的概念。但是,我仍然对这些条款感到困惑。我试图自己使用谷歌来消除它们的歧义,但似乎没有一个明确的答案。因此,我的问题是以下术语的确切含义是什么:
- 高阶类型
- 高级类型
- 高阶种类
这三个术语都存在吗?它们之间有区别吗?有什么区别?编程语言之间的含义是否有所不同?
我还注意到 StackOverflow 有多个标签:
但是,它们都没有标签 wiki。
haskell - 映射受约束的存在限定的高阶类型
我希望我的术语是正确的。
我想做以下事情:
不幸的是,GHC 似乎无法正确推断约束并抱怨:
这有可能吗?
haskell - 我可以为 a -> b -> * 写一个更高阶的类型吗?
我知道这(->) a
是一种高阶类型* -> *
,当应用于类型参数时b
会给出类型a -> b
我可以写一种类型* -> *
,当应用于时c
会给出a -> b -> c
?
如果不是,为什么不呢?也许使用一些语言扩展和forall
?
这将让我编写函数结构为“”的 Functor 和 Applicative(以及其他类)的实例,a -> b ->
如下所示:
这将作为二进制(咖喱)函数的组合器很有用。
注意。也许这是与类型 (* -> *) -> * 相关的 Functors 和 Applicatives但我不确定,因为它超出了我的想象 :-)
haskell - 有没有办法在 Haskell 中捕获一组高阶函数?
我知道在 Haskell中不可能对函数进行模式匹配,我完全理解为什么。但是,我有两个密切相关的问题。首先,如果您想部分应用函数以供以后使用,如果它是一个元组,是否有定义和捕获返回的方法?还是我错了,这仍在尝试在我的眼皮底下匹配功能?
例如,假设我试图获得一个十的多个倍数的商和余数。那么,我该如何写这样的东西呢?
我在这里意识到,存在单独的功能,所以我可以这样做:
但是,这是一个非常特殊的情况,并且有无数其他返回元组的函数示例可以很好地概括。例如,返回列表中偶数和奇数的函数。
这引出了我的第二个问题。以上在 GHCi 中工作得很好。
更令人困惑的是,它甚至可以通过“模式匹配”来工作,就像我一开始玩的一样(q, r)
:
它在加载到 GHCi 的实际文件中也可以正常工作,即使(evens, odds)
没有。为什么这两个不同,如果第二个不能正常工作,为什么在 GHCi 中工作?可以以某种方式利用这里的不同之处吗?
java - 在 Scala/Java 中允许参数化的类/类型
我想将域实体(如在域驱动设计中)中的属性定义为具有最大长度的字符串类型。不同的属性将有不同的最大长度(以便它可以匹配数据库列数据类型)。例如,描述将是 VARCHAR2(50),而长描述将是 VARCHAR2(200)。
是否可以定义一个像 VARCHAR2(50) 这样的参数采用整数的类型?所以我只需要为所有这些类型定义一个类并将其用于不同的属性?val 描述:TextValue(50) val longDescription:TextValue(200)
scala - 具有多个类型的类型的函子实现
假设我有:
我希望能够映射结果类型 B,即我希望能够做到:
我知道我应该实现一个Functor
实例,Get
但我很挣扎,因为我不知道要使用什么类型的签名。
我尝试了以下方法:
implicit val functor:Functor[Get] = ???
implicit val functor: Functor[Lambda[(F[_], K, A) => Get[F, K, A]]] = ???
但它们似乎不是正确的类型,因为我似乎无法使用顶部所示的仿函数语法扩展。在这里表达类型的正确方法是什么?如果我使用kind-projector
插件,等效类型是什么?