2011-09-13 59 views
73

通過Haskell的前奏看,我see a functionconstHaskell Prelude中'const'的含義是什麼?

const x _ = x 

我似乎無法找到有關此功能相關的任何東西。

有什麼意義?任何人都可以舉個例子說明這個函數可以用在哪裏?

+5

一個例子:'backgroundColor :: Text - > Color'是給我的'backgroundColor = const White' – Zhen

回答

68

它是傳遞給高階函數時,你不需要他們所有的靈活性非常有用。例如,一元序列算>>可以在一元綁定運營商的角度來定義

x >> y = x >>= const y 

這有點整潔比使用拉姆達

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

,你甚至可以用它指向自由

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

雖然我不是特別建議,在這種情況下。

+8

+1。當使用解析器組合器時,它也經常出現。 –

+37

啊,所以它更像是一個'函數發生器' - 我使用它有一個參數,它給了我一個函數(帶一個參數),它總是返回一個常量值。因此'map(const 42)[1..5]'產生'[42,42,42,42,42]'。 – stusmith

+2

stusmith:你懂了。 'const'對於應用單個參數來產生一個需要的函數(比如傳遞給'map')是有用的。 – Conal

24

要添加到哈馬爾的優良直接回答:不起眼的功能,如constid是因爲出於同樣的原因高階函數,他們是在SKI combinator calculus根本真的很有用。

不,我認爲Haskell的前奏職能在正式系統或任何有意識後模仿。只是在haskell中創建豐富的抽象是非常容易的,所以你經常會看到這些類型的理論事物顯得實際上有用。

無恥的插頭,但我的博客上講述了(->)應用型實例如何實際上是SK組合程序here,如果這是你到之類的話。

+7

那麼,SKI組合器肯定會影響Prelude。我記得和Joe Fasel爭論是否應該包含S combinator。 – augustss

+4

順便說一句,'(( - >)e)'也是讀者單子 - 「Reader」等只是'newtype'包裝 - 而'ask'函數則是'id',所以這就是'我'combinator以及。如果你看看Haskell Curry原來的BCKW基礎,'B','K'和'W'分別是'fmap','return'和'join'。 –

+1

答案中的博客鏈接已死亡。它現在應該指向這裏:http://brandon.si/code/do-applicative-functors-generalize-the-s-k-combinators/ – nsxt

19

使用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在這裏使用 「忘記」 關於輸入。

11

另一個用途是實現具有其不應該被評估僞參數(用於解決歧義類型)類的成員函數。可以在Data.bits中的例子:

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

通過使用const我們明確地說我們正在定義常量值。

就我個人而言,我不喜歡使用虛擬參數,但是如果它們在類中使用,那麼這是編寫實例的一種相當不錯的方式。

13

我似乎無法找到任何有關此功能的相關信息。

許多其他答案討論const相對深奧的(至少對新來的)應用程序。這裏有一個簡單的例子:你可以使用const來擺脫一個帶有兩個參數的lambda表達式,拋出第一個參數,但對第二個參數做一些有趣的事情。

例如,下面的(低效!)實現的length

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

可以改寫爲

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

這也許是更優雅。

表達const (1+)確實相當於\_ acc -> 1 + acc,因爲它需要一個參數,拋出它帶走,並返回部(1+)

+2

花了我5分鐘瞭解這是如何工作:) –

1

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允許我們引入常量。有趣的名字如何與意義聯繫起來!

然後我概括這個想法與應用型,讓您可以在一個毫無意義的風格編寫的任何函數(只要您有可用的功能情況分析,如maybeeitherbool)。 const再一次扮演介紹常數的角色。你可以在Data.Function.Tacit包中看到這項工作。

當你抽象地開始目標,然後努力實現時,你會對答案感到驚訝。也就是說,任何一個功能都可能與機器中的任何一個齒輪一樣神祕。但是,如果您退回到整個機器的視野,您可以瞭解該齒輪所需的環境。

相關問題