Haskell 中的部分应用类型

2023-12-15

基于this问题,在这段代码中

data Promise a b =  Pending (a -> b) | Resolved b | Broken

instance Functor (Promise x) where
    fmap f (Pending g) = Pending (f . g)

IF

g :: a -> b

then

Pending g :: Promise a b

also

f :: b -> c

因为存在f . g.

这意味着

Pending (f . g) :: Promise a c`.

包起来

fmap :: (b -> c) -> Promise a b -> Promise a c

Now fmap单独有这个签名(适应上面)

fmap :: Functor f => (b -> c) -> f b -> f c

仅当您假设f = Promise a。虽然最终产品看起来很合理,但您如何解释这种类型f或者等效地,部分应用的承诺的类型是什么Promise a?


在类型级别你有另一种编程语言,almost-哈斯克尔。特别是,您可以将类型视为具有构造函数并且能够部分应用。

为了更严格地看待这一点,我们引入了“类型的类型”,称为“种类”。例如,类型构造函数Int有善良

Int ::: *

我写的地方(:::)阅读“has kind”,尽管这不是有效的 Haskell 语法。现在我们还有“部分应用类型构造函数”,例如

Maybe ::: * -> *

它的函数类型就像您在值级别所期望的那样。


类型的概念有一个非常重要的概念——只有当值是类型时才可以实例化类型*。或者,例如,不存在类型的值Maybe

x :: Maybe
x = -- .... what!

事实上,甚至不可能表达除*我们期望该类型描述值的任何地方。

这导致 Haskell 中“类型级函数”的能力受到某种限制,因为我们不能普遍传递“未应用的类型构造函数”,因为它们并不总是有意义。相反,整个系统的设计使得只能构建合理的类型。

但允许表达这些“高级类型”的地方是类型类定义。


如果我们启用KindSignatures然后我们就可以直接写我们的类型的种类了。出现这种情况的一个地方是类定义中。这是Show

class Show (a :: *) where
  show :: a -> String
  ...

这是完全自然的,因为该类型的出现a在方法的签名中Show是有价值观的。

但当然,正如您在这里指出的,Functor是不同的。如果我们写出它的签名,我们就会明白为什么

class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b

这是一种非常新颖的多态性,更高级的多态性,所以你需要花一点时间来理解它。但值得注意的是f只出现在方法中Functor 正在应用到其他一些类型a and b。特别是,像这样的课程会被拒绝

class Nope (f :: * -> *) where
  nope :: f -> String

因为我们告诉系统f有善良(* -> *)但我们使用它就好像它可以实例化值,就好像它很友善一样*.


一般情况下我们不需要使用KindSignatures因为 Haskell 可以直接推断签名。例如,我们可以(事实上确实如此)写

class Functor f where
  fmap :: (a -> b) -> f a -> f b

哈斯克尔推断出这种f必须是(* -> *)因为它似乎适用于a and b。同样,如果我们编写不一致的内容,我们可能会失败“种类检查”,就像我们无法通过类型检查一样。例如

class NopeNope f where
  fmap :: f -> f a -> a

暗示f有善良* and (* -> *)这是不一致的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Haskell 中的部分应用类型 的相关文章

  • 这个记忆的斐波那契函数是如何工作的?

    在我正在做的函数式编程课程的当前练习作业中 我们必须制作给定函数的记忆版本 为了解释记忆化 给出以下示例 fiblist fibm x x lt 0 fibm 0 0 fibm 1 1 fibm n fiblist n 1 fiblist
  • 为什么 Haskell 的默认字符串实现是一个字符链接列表?

    Haskell 默认值的事实String众所周知 实现在速度和内存方面都效率不高 据我所知 lists一般来说 在 Haskell 中实现为单链表 并且适用于大多数小型 简单数据类型 例如Int 这似乎不是一个好主意 但是对于String这
  • Haskell 下划线与显式变量

    我已经学习 Haskell 几个星期了 我有一个关于下划线的使用的问题 作为函数参数 我认为用一个具体的例子来问我的问题会更好 假设我想定义一个函数 根据提供的索引提取列表的元素 是的 我意识到 已经是预先定义的 我可以定义该函数的两种方法
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 持久 selectList 导致错误“无法将类型‘BaseBackend backend0’与‘SqlBackend’匹配”

    我遇到以下编译错误 Couldn t match type BaseBackend backend0 with SqlBackend arising from a use of runSqlite The type variable bac
  • 将 num 的签名键入 double?

    我才刚刚开始为你学习 Haskell 以获得伟大的好处 并且我在类型类方面遇到了一些麻烦 我想创建一个接受任何数字类型并强制其为双精度的函数 我的第一个想法是定义 numToDouble Num gt Double 但我认为这不起作用 因为
  • Haskell - 用防护罩替换外壳

    我想知道在这部分代码中是否可以用守卫替换 case 语句 firstFunction String gt Maybe MyType secondFunction MyType gt Integer myFunction String gt
  • 以下两个 lambda 函数的空间复杂度

    我正在阅读以下内容 https en wikibooks org wiki Haskell Graph reduction https en wikibooks org wiki Haskell Graph reduction 其内容如下
  • 在 Yesod 生态系统中,对某些文本进行 urlencode 的最佳方式是什么?

    我想对一些文本进行 url 编码 例如 用 20 替换每个空格等 我找到了 HTTP Network HTTP Base urlEncode 并且可以使用它 但我想知道是否还有其他通常在 Yesod 生态系统中使用的东西 不幸的是 由于 U
  • Haskell 中的尾递归字符串分割

    我正在考虑分割字符串的问题s在一个字符处c 这表示为 break c s 其中 Haskell 库定义break c 足够接近 br br s h t if c h then s else let h t br t in h h t 假设我
  • 用于遇到 [...] 的 Haskell Parsec 解析器

    我正在尝试使用 Parsec 在 Haskell 中编写一个解析器 目前我有一个可以解析的程序 test x 1 2 3 end 执行此操作的代码如下 testParser do reserved test v lt identifier
  • 有没有更好的方法将 UTC 时间转换为大纪元时间?

    我想将文件的修改时间设置为从 exif 数据获取的时间 为了从 exif 获取时间 我发现 Graphics Exif getTag Exif gt String gt IO Maybe String 要设置文件修改时间 我发现 Syste
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 管道:多个流消费者

    我编写了一个程序来计算语料库中 NGram 的频率 我已经有一个函数 它消耗一串令牌并生成一个订单的 NGram ngram Monad m gt Int gt Conduit t m t trigrams ngram 3 countFre
  • 如何打乱列表?

    如何从一组数字 1 2 3 直到我击中x 我的计划是重新调整列表 1 2 3 并把它砍在x chopAt 3 2 3 1 2 3 chopAt 3 2 1 3 2 1 3 chopAt 3 3 1 2 3 chopAt chopAt x y
  • 迭代打印列表中的每个整数

    假设我有一个整数列表l 1 2 我想打印到stdout Doing print l产生 1 2 假设我想打印不带大括号的列表 map print l产生 No instance for Show IO arising from a use
  • 约束包如何工作?

    背后的想法数据 约束 Forall http hackage haskell org packages archive constraints 0 3 2 doc html src Data Constraint Forall html据我
  • 如何在haskell中用另一个字符串替换一个字符串

    我想用不同的字符串替换输入文件中的字符串 我正在寻找一种方法 但似乎我只能逐个字符地更改字符串 例如在我下面的代码中 replace String gt String replace replace x xs if x then y rep
  • 如何同时将透镜(或任何其他光学器件)视为吸气剂和设置剂?

    我正在尝试编写一个通用记录更新程序 它允许人们轻松更新记录中的字段existing记录 字段形状相似incoming记录 这是我到目前为止所拥有的 applyUpdater fields existing incoming let gett
  • Haskell:对 Num 类型类的使用感到困惑

    我很困惑为什么这有效 f Num a gt a gt a f x x 42 但这并没有 g Num a gt a gt a g x x 4 2 我本来就明白Num包含实现运算符的所有类型 因此 如果42 is an Int and 4 2

随机推荐