2016-09-27 63 views
9

我对SumProduct newtypes的理解是它们用作数字类型的monoidial包装。我会明白Functor实例,但为什么还有Applicative,Monad其他任何看似无用的实例?我知道他们在数学上没问题(同构于Identity modad,对吧?)但是用例是什么?例如,如果有Applicative Sum实例,我预计会在某处遇到类型为Sum (a -> b)的值。我无法想象这可能会有用。Sum和产品的Applicative/Monad实例的用途是什么?

+4

我同意,这些事例似乎没有任何意义。明确“因为我们可以”的情况。 – leftaroundabout

+1

我现在没有权限访问GHCi,但是有可能它们可以用来做'x :: Sum Int; x = do {1; 2; 3; 4; 5}'? – bheklilr

+2

@bheklilr它“有效”,并返回'总和5',因为'总和'是身份单子。 – chi

回答

11

这种情况下是便于吊装任意函数在事情发生到现在住一个SumProduct内工作。例如,人们可能会想像想要对Sum中的某些内容进行按位操作,而不是裸露;然后liftA2 (.&.) :: Sum Int -> Sum Int -> Sum Int(例如)。

人们还可以通过给Bits实例Sum,但推广该技术将需要Sum的实现者来预测人们可能曾经想要做的每一项操作,这似乎是一个艰巨的任务提供了这种操作。提供ApplicativeMonad实例为用户提供了一次全部翻译,以提升他们喜欢的任何功能 - 包括Sum的实施者未预测的有用功能。

+0

是的,但这可以说是滥用'Applicative'类。为了这个目的,使用['Iso' combinators](http://hackage.haskell.org/package/lens-4.14/docs/Control-Lens-Iso.html)更好。 – leftaroundabout

+1

@leftaroundabout你能否仔细说一下'Iso'组合器更好?天真地说,它们看起来像一个奇怪的折衷:它是一个非常沉重的依赖关系(当然不是应该被放入基地的依赖关系),并且提升两个或更多参数函数的语法看起来比单个应用“liftA2”更冗长。 –

+1

@leftaroundabout,当我看着'au'和'auf',我的眼睛掠过。 – dfeuer

3

这样的值通常由二元运算符的部分应用产生。假设FunctorApplicative情况类似

import Control.Applicative 
import Data.Monoid 

instance Functor Sum where 
    fmap f (Sum x) = Sum (f x) 

instance Applicative Sum where 
    pure = Sum 
    (Sum f) <*> (Sum x) = Sum (f x) 

,那么你可以看到Sum (a -> b)值怎么会出现。

> :t (*) <$> (Sum 5) 
(*) <$> (Sum 5) :: Num a => Sum (a -> a) 

> (*) <$> (Sum 5) <*> (Sum 10) 
Sum {getSum = 50} 
+4

由于'Num'实例,'Sum 5 * Sum 10'也有效。 – chi