- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我开始理解 forall
关键字如何在所谓的“存在类型”中使用,如下所示:
data ShowBox = forall s. Show s => SB s
然而,这只是 forall
的使用方式的一个子集,我根本无法理解它在这样的事情中的使用:
runST :: forall a. (forall s. ST s a) -> a
或者解释为什么它们不同:
foo :: (forall a. a -> a) -> (Char, Bool)
bar :: forall a. ((a -> a) -> (Char, Bool))
或者整个RankNTypes
内容...
我倾向于更喜欢清晰、无行话的英语,而不是学术环境中常见的语言。我尝试阅读的大多数解释(我可以通过搜索引擎找到的解释)都存在以下问题:
runST
、foo
和 bar
上面)。所以...
关于实际问题。任何人都可以用清晰、简单的英语完全解释 forall
关键字(或者,如果它存在于某个地方,请指出我错过的这样一个清晰的解释),并且不假设我是一名数学家用行话来说?
最佳答案
让我们从代码示例开始:
foob :: forall a b. (b -> b) -> b -> (a -> b) -> Maybe a -> b
foob postProcess onNothin onJust mval =
postProcess val
where
val :: b
val = maybe onNothin onJust mval
此代码无法在普通 Haskell 98 中编译(语法错误)。它需要扩展来支持 forall
关键字。
基本上,forall
有 3 种不同常见用途关键字(或者至少看起来如此),并且每个关键字都有自己的 Haskell 扩展:ScopedTypeVariables
, RankNTypes
/Rank2Types
, ExistentialQuantification
.
上面的代码在启用其中任何一个的情况下都不会出现语法错误,但仅使用 ScopedTypeVariables
进行类型检查。已启用。
作用域类型变量:
作用域类型变量有助于指定 where
内代码的类型条款。它使得b
在val :: b
与 b
相同在foob :: forall a b. (b -> b) -> b -> (a -> b) -> Maybe a -> b
.
一个令人困惑的点:当您省略 forall
时,您可能会听到这一点。从类型来看,它实际上仍然隐式存在。 (from Norman's answer: "normally these languages omit the forall from polymorphic types")。此声明是正确的,但它指的是 forall
的其他用途,而不是ScopedTypeVariables
使用。
排名-N-类型:
让我们从mayb :: b -> (a -> b) -> Maybe a -> b
开始相当于 mayb :: forall a b. b -> (a -> b) -> Maybe a -> b
,除了,当 ScopedTypeVariables
时已启用。
这意味着它适用于每个 a
和b
.
假设您想做这样的事情。
ghci> let putInList x = [x]
ghci> liftTup putInList (5, "Blah")
([5], ["Blah"])
这个 liftTup
的类型必须是什么?这是liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)
。要了解原因,让我们尝试编写代码:
ghci> let liftTup liftFunc (a, b) = (liftFunc a, liftFunc b)
ghci> liftTup (\x -> [x]) (5, "Hello")
No instance for (Num [Char])
...
ghci> -- huh?
ghci> :t liftTup
liftTup :: (t -> t1) -> (t, t) -> (t1, t1)
“嗯..为什么 GHC 推断元组必须包含两个相同类型?让我们告诉它它们不必是”
-- test.hs
liftTup :: (x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)
ghci> :l test.hs
Couldnt match expected type 'x' against inferred type 'b'
...
嗯。所以这里 GHC 不允许我们申请 liftFunc
上v
因为v :: b
和liftFunc
想要一个x
。我们确实希望我们的函数能够接受任何可能的 x
!
{-# LANGUAGE RankNTypes #-}
liftTup :: (forall x. x -> f x) -> (a, b) -> (f a, f b)
liftTup liftFunc (t, v) = (liftFunc t, liftFunc v)
所以这不是liftTup
适用于所有人 x
,这是它得到的函数的作用。
存在量化:
让我们举个例子:
-- test.hs
{-# LANGUAGE ExistentialQuantification #-}
data EQList = forall a. EQList [a]
eqListLen :: EQList -> Int
eqListLen (EQList x) = length x
ghci> :l test.hs
ghci> eqListLen $ EQList ["Hello", "World"]
2
这与 Rank-N-Types 有什么不同?
ghci> :set -XRankNTypes
ghci> length (["Hello", "World"] :: forall a. [a])
Couldnt match expected type 'a' against inferred type '[Char]'
...
对于 Rank-N-类型,forall a
意味着你的表达必须符合所有可能的a
s。例如:
ghci> length ([] :: forall a. [a])
0
空列表可以用作任何类型的列表。
因此,对于存在量化,forall
位于data
定义意味着,包含的值可以是任何合适的类型,而不是它必须是所有合适的类型类型。
关于haskell - Haskell/GHC 中的 `forall` 关键字有什么作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3071136/
今天有小伙伴给我留言问到,try{...}catch(){...}是什么意思?它用来干什么? 简单的说 他们是用来捕获异常的 下面我们通过一个例子来详细讲解下
我正在努力提高网站的可访问性,但我不知道如何在页脚中标记社交媒体链接列表。这些链接指向我在 facecook、twitter 等上的帐户。我不想用 role="navigation" 标记这些链接,因
说现在是 6 点,我有一个 Timer 并在 10 点安排了一个 TimerTask。之后,System DateTime 被其他服务(例如 ntp)调整为 9 点钟。我仍然希望我的 TimerTas
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我就废话不多说了,大家还是直接看代码吧~ ? 1
Maven系列1 1.什么是Maven? Maven是一个项目管理工具,它包含了一个对象模型。一组标准集合,一个依赖管理系统。和用来运行定义在生命周期阶段中插件目标和逻辑。 核心功能 Mav
我是一名优秀的程序员,十分优秀!