it-swarm.cn

Haskell Prelude中'const'的重点是什么?

通过Haskell Prelude,我 看一个函数const

const x _ = x

我似乎无法找到有关此功能的任何相关内容。

重点是什么?任何人都可以举例说明这个函数的用途吗?

81
stusmith

当您不需要所有灵活性时,它可用于传递到高阶函数。例如,monadic序列运算符>>可以根据monadic绑定运算符来定义

x >> y = x >>= const y

它比使用lambda有点整洁

x >> y = x >>= \_ -> y

你甚至可以无点使用它

(>>) = (. const) . (>>=)

虽然在这种情况下我并不特别推荐。

79
hammar

添加到hammar的优秀直接答案:像constid这样的简单函数作为高阶函数非常有用,因为它们是 基础 SKI组合子微积分中

并不是说我认为haskell的前奏函数是在正式系统之后有意识地建模的。只是在haskell中创建丰富的抽象非常容易,所以你经常会看到这些类型的理论事物在实际上很有用。

无耻的插件,但我在博客上写了(->)的Applicative实例实际上是SK组合器 这里 ,如果这是你进入的那种东西。

26
jberryman

使用const的一个简单示例是Data.Functor.(<$)。有了这个功能,你可以说:我这里有一个带有无聊内容的仿函数,但我希望在其中有其他有趣的东西,而不改变仿函数的形状。例如。

import Data.Functor

42 <$ Just "boring"
--> Just 42

42 <$ Nothing
--> Nothing

"cool" <$ ["nonsense","stupid","uninteresting"]
--> ["cool","cool","cool"]

定义是:

(<$) :: a -> f b -> f a
(<$) =  fmap . const

或者写得没有意义:

cool <$ uncool =  fmap (const cool) uncool

你看到如何使用const来“忘记”输入。

22
Landei

我似乎无法找到有关此功能的任何相关内容。

许多其他答案讨论了const的相对深奥的(至少是新手)应用程序。这里有一个简单的例子:你可以使用const去掉一个带有两个参数的lambda,扔掉第一个参数,但用第二个抛出一些有趣的东西。

例如,以下(效率低下!)length的实现,

length' = foldr (\_ acc -> 1 + acc) 0

可以改写为

length' = foldr (const (1+)) 0

这可能更优雅。

表达式const (1+)确实在语义上等同于\_ acc -> 1 + acc,因为它接受一个参数,将其抛弃,并返回(1+)部分。

16
jubobs

另一个用途是实现具有伪参数的类成员函数,该伪参数不应被评估(用于解析模糊类型)。可以在Data.bits中的示例:

instance Bits Int where
  isSigned = const True
  bitSize  = const wordSize
  ...

通过使用const,我们明确地说我们正在定义常量值。

我个人不喜欢使用伪参数,但如果在类中使用它们,那么这是编写实例的一种相当不错的方式。

15
Jonas Duregård

假设您要创建一个Nothings的列表,该列表等于字符串的长度。当const返回其第一个参数时,无论第二个参数如何,您都可以:

listOfNothings :: String -> [Maybe Char]
listOfNothings = (map . const) Nothing

或者,更明确地说:

listOfNothing st = map (const Nothing) st
2
A.Saramet

const可能只是您正在寻找的与其他函数一起使用的实现。这是我发现的一个例子。

假设我们想要将2元组的结构重写为另一个2元组结构。我可能会这样表达:

((a,b),(c,d)) ⇒ (a,(c,(5,a)))

我可以通过模式匹配给出一个直接的定义:

f ((a,b),(c,d)) = (a,(c,(5,a)))

如果我想要这种重写的无意义(默认)解决方案怎么办?有些思考和摆弄以后,答案是我们可以用(&&&), const, (.), fst, snd表达任何重写。请注意(&&&)来自Control.Arrow

使用这些函数的示例的解决方案是:

(fst.fst &&& (fst.snd &&& (const 5 &&& fst.fst)))

注意与(a,(c,(5,a)))的相似性。如果我们用&&&替换,会怎么样?然后它写道:

(fst.fst, (fst.snd, (const 5, fst.fst)))

注意a是第一个元素的第一个元素,也就是fst.fst的项目。注意c是第二个元素的第一个元素,也就是fst.snd的项目。也就是说,变量成为其源头的途径。

const允许我们引入常量。有趣的是这个名字如何与意义排列在一起!

然后我用Applicative概括了这个想法,这样你就可以用无意义的方式编写任何函数(只要你有案例分析作为函数提供,例如maybeeitherbool)。同样,const扮演引入常量的角色。您可以在 Data.Function.Tacit package中看到这项工作。

当你开始抽象地,在目标上,然后努力实现时,你可能会对答案感到惊讶。也就是说,任何一个功能都可能与机器中的任何一个齿轮一样神秘。但是,如果您向后拉以使整个机器进入视图,则可以了解必要的上下文。

2
erisco