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 的完美示例。

广告