- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
概括
我有一个类型类,我想为它写一些“通用术语”。我有两个问题:
:t
向 GHCi 询问通用术语的类型有效,但使用该推断类型失败 - 为什么? TypeApplications
使用类型类的方法? Main.hs
包含一个类型类
F
并输入
Empty
这是
F
的一个实例.
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Main where
import GHC.Types (Type)
class F (f :: k -> Type) where
type Plus f (a :: k) (b :: k) :: k
zero :: f a
plus :: f a -> f b -> f (Plus f a b)
data Empty (a :: Type) = Empty
instance F Empty where
type Plus Empty a b = (a, b)
zero = Empty
plus _ _ = Empty
1. 推断类型不起作用?
F
.例如,
plus zero zero
.
*Main> :t plus zero zero
plus zero zero :: F f => f (Plus f a b)
令人惊讶的是,如果我尝试分配这个术语,我会得到一个错误。也就是说,如果我将以下内容添加到
Main.hs
:
-- This doesn't work.
plusZero :: F f => f (Plus f a b)
plusZero = plus zero zero
在 GHCi 中重新加载文件报错:
• Couldn't match type ‘Plus f a0 b0’ with ‘Plus f a b’
Expected type: f (Plus f a b)
Actual type: f (Plus f a0 b0)
NB: ‘Plus’ is a non-injective type family
The type variables ‘a0’, ‘b0’ are ambiguous
• In the expression: plus zero zero
In an equation for ‘plusZero’: plusZero = plus zero zero
我的第一个问题是:为什么 GHCi 似乎推断类型,但当我明确注释该术语时拒绝它?
TypeApplications
而不是注释
zero
的类型来解决第一个问题。条款:
-- This works
plusZero1 :: forall f a b . F f => f (Plus f a b)
plusZero1 = plus (zero :: f a) (zero :: f b)
但是,当条款变大时,这有点笨拙。我想做的是使用
TypeApplications
.我试过这个:
-- This doesn't work
plusZero2 :: forall f a b . F f => f (Plus f a b)
plusZero2 = plus @f @a @b zero zero
但GHCI提示:
• Expecting one more argument to ‘f’
Expected a type, but ‘f’ has kind ‘k -> *’
• In the type ‘f’
In the expression: plus @f @a @b zero zero
In an equation for ‘plusZero2’: plusZero2 = plus @f @a @b zero zero
• Relevant bindings include
plusZero2 :: f (Plus f a b) (bound at Main.hs:36:1)
奇怪的是,如果我先定义附加函数
plus'
和
zero'
如下,一切都按预期工作:
zero' :: forall f a . F f => f a
zero' = zero
plus' :: forall f a b . F f => f a -> f b -> f (Plus f a b)
plus' = plus
-- This works fine
plusZero3 :: forall f a b . F f => f (Plus f a b)
plusZero3 = plus' @f @a @b zero' zero'
所以看来我还没有理解
TypeApplications
适用于类型类方法。
plus
一起使用和
zero
无需定义附加函数
plus'
和
zero'
?
最佳答案
- Inferred Types don't work?
Plus f a b
是一个非内射类型族。对于所有 GHC 在类型检查时所知道的,它可以定义为
Plus f a b = a
为所有
f
,
a
, 和
b
.
forall
s)
foo :: forall f a b. F f => f (Plus f a b)
我们写
bar :: forall f a b. F f => f (Plus f a b)
bar = foo
这不应该输入检查(!),因为它本质上是模棱两可的。作为人类的程序员可能期望编译器推断出这些类型:
bar :: forall f a b. F f => f (Plus f a b)
bar = foo @f @a @b
但是,可能还有其他正确的推断类型!确实,如果
Plus
如上所述定义,这也将类型检查:
bar :: forall f a b. F f => f (Plus f a b)
bar = foo @f @a @String
使用它,
foo
将产生
f (Plus f a String)
与
f (Plus f a b)
相同,所以一切类型检查。因为程序员可能打算使用
@b
以外的其他东西。 ,我们在这里停止报告类型错误的歧义。
foo
链接到新鲜的未知类型变量:
bar :: forall f a b. F f => f (Plus f a b)
bar = foo @xf @xa @xb
然后,统一发生:
foo @xf @xa @xb
的类型是
xf (Plus xf xa xb)
这与提供的签名统一以查找未知数:
xf (Plus xf xa xb) ~ f (Plus f a b)
由此我们应用统一算法:
xf ~ f
Plus xf xa xb ~ Plus f a b
所以我们找到未知的类型
xf
, 代入我们得到:
xf ~ f
Plus f xa xb ~ Plus f a b
然而,我们到此为止。我们无法推断
xa ~ a
和
xb ~ b
因为类型族不是单射的。
- Using TypeApplications instead of annotations
@k
论点,因为这发生在类里面。使用
:t +v
用所有
forall
显示真实类型年代:
> :t +v plus
plus
:: forall k (f :: k -> *) (a :: k) (b :: k).
F f =>
f a -> f b -> f (Plus f a b)
路过
@k
也有效:
plusZero2 :: forall k (f :: k -> Type) a b . F f => f (Plus f a b)
plusZero2 = plus @k @f @a @b zero zero
或者,让编译器推断
@k
:
plusZero2 :: forall f a b . F f => f (Plus f a b)
plusZero2 = plus @_ @f @a @b zero zero
关于haskell - 如何将 TypeApplications 与 typeclass 方法一起使用,为什么 GHCi 会推断出我无法使用的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65369389/
尝试使用集成到 QTCreator 的表单编辑器,但即使我将插件放入 QtCreator.app/Contents/MacOS/designer 也不会显示。不过,相同的 dylib 文件确实适用于独
在此代码示例中。 “this.method2();”之后会读到什么?在返回returnedValue之前会跳转到method2()吗? public int method1(int returnedV
我的项目有通过gradle配置的依赖项。我想添加以下依赖项: compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', v
我将把我们基于 Windows 的客户管理软件移植到基于 Web 的软件。我发现 polymer 可能是一种选择。 但是,对于我们的使用,我们找不到 polymer 组件具有表格 View 、下拉菜单
我的项目文件夹 Project 中有一个文件夹,比如 ED 文件夹,当我在 Eclipse 中指定在哪里查找我写入的文件时 File file = new File("ED/text.txt"); e
这是奇怪的事情,这个有效: $('#box').css({"backgroundPosition": "0px 250px"}); 但这不起作用,它只是不改变位置: $('#box').animate
这个问题在这里已经有了答案: Why does OR 0 round numbers in Javascript? (3 个答案) 关闭 5 年前。 Mozilla JavaScript Guide
这个问题在这里已经有了答案: Is the function strcmpi in the C standard libary of ISO? (3 个答案) 关闭 8 年前。 我有一个问题,为什么
我目前使用的是共享主机方案,我不确定它使用的是哪个版本的 MySQL,但它似乎不支持 DATETIMEOFFSET 类型。 是否存在支持 DATETIMEOFFSET 的 MySQL 版本?或者有计划
研究 Seam 3,我发现 Seam Solder 允许将 @Named 注释应用于包 - 在这种情况下,该包中的所有 bean 都将自动命名,就好像它们符合条件一样@Named 他们自己。我没有看到
我知道 .append 偶尔会增加数组的容量并形成数组的新副本,但 .removeLast 会逆转这种情况并减少容量通过复制到一个新的更小的数组来改变数组? 最佳答案 否(或者至少如果是,则它是一个错
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
noexcept 函数说明符是否旨在 boost 性能,因为生成的对象中可能没有记录异常的代码,因此应尽可能将其添加到函数声明和定义中?我首先想到了可调用对象的包装器,其中 noexcept 可能会产
我正在使用 Angularjs 1.3.7,刚刚发现 Promise.all 在成功响应后不会更新 angularjs View ,而 $q.all 会。由于 Promises 包含在 native
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我正在编写一个玩具(物理)矢量库,并且遇到了 GHC 坚持认为函数应该具有 Integer 的问题。是他们的类型。我希望向量乘以向量以及标量(仅使用 * ),虽然这可以通过仅使用 Vector 来实现
PHP 的 mail() 函数发送邮件正常,但 Swiftmailer 的 Swift_MailTransport 不起作用! 这有效: mail('user@example.com', 'test
我尝试通过 php 脚本转储我的数据,但没有命令行。所以我用 this script 创建了我的 .sql 文件然后我尝试使用我的脚本: $link = mysql_connect($host, $u
使用 python 2.6.4 中的 sqlite3 标准库,以下查询在 sqlite3 命令行上运行良好: select segmentid, node_t, start, number,title
我最近发现了这段JavaScript代码: Math.random() * 0x1000000 10.12345 10.12345 >> 0 10 > 10.12345 >>> 0 10 我使用
我是一名优秀的程序员,十分优秀!