为什么我们在那里使用幺半群和仿函数?

时间:2014-05-28 14:01:15

标签: haskell functor monoids

我是哈斯克尔的新人 我无法弄清楚为什么我们在下面的代码中使用monoid和instance Functor Matrix以及instance Functor Matrix如何工作?

instance Functor Matrix where
    fmap f (M n m v) = M n m $ fmap (fmap f) v

instance Num a => Num (Matrix a) where
    fromInteger = M 1 1 . V.singleton . V.singleton . fromInteger
    negate = fmap negate
    (+) = add
    (*) = mult
    abs = fmap abs
    signum = fmap signum

scalarMult :: Num a => a -> Matrix a -> Matrix a
    scalarMult = fmap . (*)

我知道negate(*)abssignum需要仿函数,但我需要详细说明。请帮帮我。

1 个答案:

答案 0 :(得分:3)

Functor是一个非常简单的事情,名称复杂。简单地说,Functor是容器,您可以通过fmap函数将函数映射到其值。列表是最熟悉的Functor,因为fmap只是map。其他Functor包括MaybeIOEither a

在此代码段中,您将Matrix定义为Functor,因此您告诉编译器Matrix是一个可以映射函数的容器。出于此问题的目的,fmap用于定义Num类型类中的几个函数。很容易看出它是如何工作的(假设有一个fromList :: [[a]] -> Matrix a函数):

> fmap id $ fromList [[1, 2], [3, 4]]
fromList [[1, 2], [3, 4]]
> fmap (+1) $ fromList [[1, 2], [3, 4]]
fromList [[2, 3], [4, 5]]
> fmap show $ fromList [[1, 2], [3, 4]]
fromList [["1", "2"], ["3", "4"]]

对于其他Functor s:

> fmap (+1) [1, 2, 3]
[2, 3, 4]
> fmap (*10) (Just 1)
Just 10
> fmap (*10) Nothing
Nothing

至于为什么在Data.Monoid的来源中导入了Data.Matrix,这完全是因为功能

-- | Display a matrix as a 'String' using the 'Show' instance of its elements.
prettyMatrix :: Show a => Matrix a -> String
prettyMatrix m@(M _ _ v) = unlines
 [ "( " <> unwords (fmap (\j -> fill mx $ show $ m ! (i,j)) [1..ncols m]) <> " )" | i <- [1..nrows m] ]
 where
  mx = V.maximum $ fmap (V.maximum . fmap (length . show)) v
  fill k str = replicate (k - length str) ' ' ++ str

如果作者选择使用<>而不是++将字符串连接在一起,那么对列表Monoid进行相当平凡的使用。它与Matrix类型完全没有关系。