2012-10-30 141 views
3

我在Haskell中做的一些計算的一部分產生了一個函數列表,它將Float映射到Float。我想一個參數,適用於所有這些功能,比如:Haskell:映射函數應用程序

-- x :: Float 
-- functions :: [Float -> Float] 
map (\f -> f x) functions 

有沒有辦法做到這一點而不使用一個扔掉的lambda函數的?我搜索Hoogle我認爲簽名應該是([a -> b] -> a -> [b])沒有運氣。

+0

請參閱http://stackoverflow.com/questions/11709350 –

+1

只是單挑,有一個名爲'pointfree'('cabal install pointfree')的程序,可以自動執行這些類型的縮減。例如'map(\ f - > f x)fs'根據需要變成'map($ x)fs'。 – huon

回答

9

可以使用$運營商,這僅僅是功能應用:(這預示着x在範圍爲表達)

map ($ x) functions 

Hoogle唯一能找到的功能,而不是任意表達式。由於您使用的是map,因此您希望搜索諸如(a -> b) -> a -> b之類的函數,而不是涉及列表的任何內容。給定一個正常的函數,將它傳遞給map使其對列表起作用。

+0

是的,我覺得我對簽名有些困惑。謝謝!我理解'$'如何定義優先級,但是在這種情況下它是如何工作的? –

+2

運算符的定義非常簡單:'f $ x = f x'。所以它實際上只是功能應用,作爲一個操作員。當你部分應用它時,你會得到一些等同於'\ f - > f $ x'的東西;使用上面的定義,這可以解釋爲'\ f - > f x',這正是你所擁有的。 –

+0

據我所知,'map f xs'對'xs'中的每個'x'都做'f x'。所以它看起來像'$ f x',因此我的困惑! –

6

functions <*> pure x應該這樣做。先導入Control.Applicative模塊。

也可以這樣考慮:

Prelude Control.Applicative> [(1+),(2+)] <*> pure 4 
[5,6] 
Prelude Control.Applicative> [(1+),(2+)] <*> [4] 
[5,6] 
Prelude Control.Applicative> [(1+),(2+)] <*> [4,5] 
[5,6,6,7] 
Prelude Control.Applicative> [(+)] <*> [1,2] <*> [4,5] 
[5,6,6,7] 
Prelude Control.Applicative> (+) <$> [1,2] <*> [4,5] 
[5,6,6,7] 
Prelude Control.Applicative> getZipList $ ZipList [(1+),(2+)] <*> ZipList [4,5] 
[5,7] 
Prelude Control.Applicative> getZipList $ ZipList [(1+),(2+)] <*> pure 4 
[5,6] 

<$>僅僅是fmap的代名詞。根據某種語義,<*>適用於左側的應用函子中的「攜帶」,以及右側的內容。對於裸列表,語義與列表monad相同 - 進行所有可能的組合 - 將每個函數從左邊應用到右邊的每個對象,然後pure x = [x]。對於標記的列表(即,newtyped)爲ZipLists,語義是「拉鍊」應用 - 即一對一pure x = ZipList $ repeat x

+0

好吧,我有時間學習一些monads?謝謝! –

+1

不是單子,應用函子。 :) –

+2

這些函數實際上是爲應用函子定義的,而不是單子。應用程序更普遍 - 所有monad也是應用程序,但反之亦然。 –