Haskell - Functor



Functor 在 Haskell 中是一種不同型別函式表示形式,可以對其進行對映。它是實現多型性的高階概念。根據 Haskell 開發人員的說法,所有型別,例如列表、對映、樹等,都是 Haskell Functor 的例項。

Functor 是一個內建類,具有如下函式定義:

class Functor f where 
   fmap :: (a -> b) -> f a -> f b 

根據此定義,我們可以得出結論,Functor 是一個函式,它接受一個函式(例如 fmap())並返回另一個函式。在上面的示例中,fmap() 是函式 map() 的泛化表示。

在以下示例中,我們將看到 Haskell Functor 如何工作。

main = do  
   print(map (subtract 1) [2,4,8,16])      
   print(fmap (subtract 1) [2,4,8,16])   

在這裡,我們對列表進行了減法運算,使用了 map()fmap()。您可以觀察到這兩個語句將產生相同的結果,即包含元素 [1,3,7,15] 的列表。

這兩個函式都呼叫了另一個名為 subtract() 的函式來產生結果。

[1,3,7,15]
[1,3,7,15]

那麼,mapfmap 之間有什麼區別呢?區別在於它們的用法。Functor 使我們能夠在不同的資料型別中實現更多函式式特性,例如 "just" 和 "Nothing"。

main = do 
   print (fmap  (+7)(Just 10)) 
   print (fmap  (+7) Nothing)

以上程式碼將在終端上產生以下輸出:

Just 17
Nothing

Applicative Functor

Applicative Functor 是一個普通的 Functor,具有 Applicative 型別類提供的某些額外功能。

使用 Functor,我們通常將現有的函式與在其內部定義的另一個函式進行對映。但是,沒有辦法將 Functor 內部定義的函式與另一個 Functor 進行對映。這就是為什麼我們有另一個名為 Applicative Functor 的功能。此對映功能由 Control 模組下定義的 Applicative 型別類實現。此類只提供兩種方法供我們使用:一種是 pure,另一種是 <*>

以下是 Applicative Functor 的類定義。

class (Functor f) => Applicative f where   
   pure :: a -> f a   
   (<*>) :: f (a -> b) -> f a -> f b   

根據實現,我們可以使用兩種方法對映另一個 Functor:“Pure”“<*>”。“Pure” 方法應該接受任何型別的值,並且它始終會返回該值的 Applicative Functor。

以下示例演示了 Applicative Functor 如何工作:

import Control.Applicative 

f1:: Int -> Int -> Int 
f1 x y = 2*x+y  
main = do  
   print(show $ f1 <$> (Just 1) <*> (Just 2) ) 

在這裡,我們在函式 f1 的函式呼叫中實現了 Applicative Functor。我們的程式將產生以下輸出。

"Just 4"

Monoid

我們都知道 Haskell 將所有內容定義為函式的形式。在函式中,我們可以選擇將輸入作為函式的輸出。這就是 Monoid 的含義。

Monoid 是一組函式和運算子,其中輸出與其輸入無關。讓我們以函式 (*) 和整數 (1) 為例。現在,無論輸入是什麼,其輸出都將保持相同的數字。也就是說,如果將一個數字乘以 1,您將得到相同的數字。

以下是 Monoid 的型別類定義。

class Monoid m where  
   mempty :: m 
   mappend :: m -> m -> m  
   mconcat :: [m] -> m 
   mconcat = foldr mappend mempty 

請檢視以下示例以瞭解 Monoid 在 Haskell 中的用法。

multi:: Int->Int 
multi x = x * 1 
add :: Int->Int 
add x = x + 0 

main = do  
   print(multi 9)  
   print (add 7)

我們的程式碼將產生以下輸出:

9
7

在這裡,函式 "multi" 將輸入乘以 "1"。類似地,函式 "add" 將輸入與 "0" 相加。在這兩種情況下,輸出都將與輸入相同。因此,函式 {(*),1}{(+),0} 是 Monoid 的完美示例。

廣告

© . All rights reserved.