http://learnyouahaskell.com/functors-applicative-functors-and-monoids:
sequence [] = return [] sequence (a:as) = do x <- a fmap (x:) $ sequence as
的定义如下:Product
为什么newtype Product a = Product { getProduct :: a }
deriving (Eq, Ord, Read, Show, Bounded)
被迫Product
?
同一本书中的以下几段内容:
它的
Bounded
实例看起来像这样:Monoid
嗯?唯一的约束是instance Num a => Monoid (Product a) where
mempty = Product 1
Product x `mappend` Product y = Product (x * y)
!但是Num a
特别意味着Num
,而且AFAIK不受限制(与Integer
不同)。
然后进行测试:
Int
让我们看看下面的代码:
import Data.Monoid
numbers :: [Integer]
numbers = [1..100]
main = print (getProduct . mconcat . map Product $ numbers)
工作。不会失败。
那么m@m-X555LJ:~$ runhaskell wtf.hs
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
m@m-X555LJ:~$
的界限是什么? Product
有界限吗?
让我们再次播放:
Product
看来m@m-X555LJ:~$ ghci
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Prelude> minBound :: Int
-9223372036854775808
Prelude> maxBound :: Int
9223372036854775807
Prelude> import Data.Monoid
Prelude Data.Monoid> maxBound :: (Product Integer)
<interactive>:4:1: error:
• No instance for (Bounded Integer)
arising from a use of ‘maxBound’
• In the expression: maxBound :: Product Integer
In an equation for ‘it’: it = maxBound :: Product Integer
Prelude Data.Monoid> maxBound :: Product
<interactive>:5:13: error:
• Expecting one more argument to ‘Product’
Expected a type, but ‘Product’ has kind ‘* -> *’
• In an expression type signature: Product
In the expression: maxBound :: Product
In an equation for ‘it’: it = maxBound :: Product
Prelude Data.Monoid> maxBound :: (Product Int)
Product {getProduct = 9223372036854775807}
Prelude Data.Monoid>
Leaving GHCi.
m@m-X555LJ:~$
本身并不是Product
。 Bounded
是;但是Int
抛出! IIUC maxBound :: (Product Integer)
是Product deriving Bounded
在maxBound
上定义良好的保证。显然,并非总是如此。
那为什么Product
是Product
的实例?
答案 0 :(得分:6)
Product
不是Bounded
的实例(无论如何,这都是一种错误)。您错过了deriving
的实际用途。
Haskell报告中有a formal specification of derived instances:
如果 T 是由以下内容声明的代数数据类型:
data cx => T u1 … uk = K1 t11 … t1k1 | ⋅⋅⋅ | Kn tn1 … tnkn deriving (C1, …, Cm)
(其中 m≥0 ,并且如果 m = 1 可以省略括号),则可能为类 C 如果满足以下条件:
- C 是
Eq
,Ord
,Enum
,Bounded
,Show
或Read
之一。- 存在一个上下文 cx',使得对于每个构成类型 t <, cx'⇒C t ij sub> ij 。
[...]
每个派生的实例声明将具有以下形式:
instance (cx, cx′) => Ci (T u1 … uk) where { d }
[...]
这意味着类约束自动分配给类型参数。
Bounded
类引入了类方法minBound
和maxBound
,它们定义了类型的最小和最大元素。对于枚举,data
声明中列出的第一个和最后一个构造函数是界限。对于具有单个构造函数的类型,该构造函数将应用于构成类型的边界。例如,以下数据类型:data Pair a b = Pair a b deriving Bounded
将生成以下
Bounded
实例:instance (Bounded a,Bounded b) => Bounded (Pair a b) where minBound = Pair minBound minBound maxBound = Pair maxBound maxBound
对于Product
,这意味着Product a
仅是Bounded
的实例,如果a
是。