【问题标题】:Understanding Haskell's (->)?了解 Haskell 的 (->)?
【发布时间】:2018-12-15 05:01:25
【问题描述】:

在学习“高级”Haskell 时,我有几次看到(->)。 当我尝试运行:t (->) 时,ghci 失败,有时甚至官方文档也会使用这种表示法。

据我所知猜测(->)Hask 中的任何态射 - 基本上,任何 Haskell 函数。我假设这个想法是修复源端点或目标端点:例如,((->) Int) 可能意味着Int 类型的任何函数;显然,(Int (->)) 表示来自Int 的任何函数。

下一个假设是(->) 可能是一个内函子。 fmap 的实现似乎很简单:拥有a 类型的固定端点和态射f :: a -> b 可以生成((->) b) 的实例。它保留了id,但不会破坏现有的组合:即fmap(g . f) = fmap(g) . fmap(f)

所以我的第一个问题是:我说的对吗?

我的第二个问题是为什么:t (->)ghci 中失败了?

我的第三个问题有没有办法可以在真正的 Haskell 代码中使用 (->)?我需要启用一些{{ #Pragma ... 扩展吗?或者它只是一个用来解释概念的理论概念,仅此而已?

最后,最后一个问题。双重概念(<-) 存在吗?

【问题讨论】:

  • 看来这里有一些帮助:stackoverflow.com/q/9136421
  • (->) 不是一个值,所以你不能询问它的类型。但是,您可以询问它的种类:k (->) 或只是有关它的信息:i (->)((->) Int) 表示 来自 Int 类型的任何函数 - 想想 ((/) 2.0)(/ 2.0) 之间的类似区别。
  • @Alec,确实,谢谢。

标签: haskell


【解决方案1】:

-> 是函数类型的类型构造函数。 f :: A -> B 表示“f 是从某种类型 A 到某种类型 B 的函数”。

:t (->) 是一个错误,因为-> 不是一个值并且没有类型;它是一个类型(或者更确切地说是类型构造函数)。同样,:t Maybe:t Int 是错误的。

与普通运算符一样,中缀应用程序是(咖喱)前缀应用程序的语法糖;即就像x + y可以写成(+) x y((+) x) y一样,A -> B也可以写成(->) A B((->) A) B

((->) Int) 并不意味着“Int 类型的任何函数”;它是函数的类型构造函数来自 Int。它本身不是有效类型,但您可以将其应用于类型以获得有效的函数类型;例如((->) Int) String 是从IntString 的函数类型。

(Int (->)) 是一种错误;它尝试将Int 应用于(->),但Int 不接受任何参数。

(->) e 确实是任何类型eFunctor(带有fmap = (.),即函数组合)。它也是ApplicativeMonad(相当于Reader)。

所有这些都是标准的 Haskell 语法。无需语言扩展。

<- 在类型级别不存在。它是可以在表达式中使用的保留语法,例如在列表推导 ([ x * 2 | x <- [0 ..] ]) 或 do 块 (do { x <- p; return (x * 2) }) 中;它也用于其他一些上下文,但不在类型中。

【讨论】:

  • 看来-><- 都是保留的,不能(重新)定义。
  • 由于((->) Int) String 是一个有效的函数type:t ((->) Int) String 应该回复类似(Int -> String) 的内容,但是它总是失败。当:k ((->) Int) String 吐出一些意想不到的东西时:* - 它是一个占位符,字面意思是“可能是什么”?..
  • @SerejaBogolubov 您只能询问值的类型,而不是类型。类型没有类型,它们有种类。
  • @melpomene,哦,我知道了。
  • @SerejaBogolubov * 只是一种常规类型。 :k Int*:k Maybe* -> *:k Either* -> * -> *。请注意,(->) 既是类型构造函数又是种类构造函数::k (->)* -> * -> *
猜你喜欢
  • 2016-01-31
  • 1970-01-01
  • 2016-06-01
  • 1970-01-01
  • 2019-02-02
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多