Почему продукт ограничен? - PullRequest
4 голосов
/ 20 апреля 2019

http://learnyouahaskell.com/functors-applicative-functors-and-monoids:

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 в частности означает Integer, и это не ограничено (в отличие от Int), AFAIK.

Давайте проверим это тогда:

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 есть;но maxBound :: (Product Integer) бросает!IIUC Product deriving Bounded - это обещание, что maxBound четко определено для Product.Очевидно, не всегда.

Так почему Product является экземпляром Bounded?

1 Ответ

6 голосов
/ 20 апреля 2019

Product не является экземпляром Bounded (в любом случае, это будет ошибка).Вам не хватает того, что на самом деле делает * 1003.

В отчете Haskell есть формальная спецификация производных экземпляров :

Если T - это алгебраический тип данных, объявленный как:

data <em>cx</em> => <em>T</em> <em>u<sub>1</sub></em> … <em>u<sub>k</sub></em> = <em>K<sub>1</sub></em> <em>t<sub>11</sub></em> … <em>t<sub>1k<sub>1</sub></sub></em> | ⋅⋅⋅ | <em>K<sub>n</sub></em> <em>t<sub>n1</sub></em> … <em>t<sub>nk<sub>n</sub></sub></em> deriving (<em>C<sub>1</sub></em>, …, <em>C<sub>m</sub></em>)

(где m ≥ 0 , и скобки могут быть опущены, если m = 1 ) тогда объявление производного экземпляра возможно для класса C , если выполняются следующие условия:

  1. C является одним из Eq, Ord, Enum, Bounded, Show или Read.
  2. Существует контекст cx ′ такой, что cx ′ ⇒ C t ij выполняется для каждого из составляющих типов t ij .

[...]

Каждыйобъявление производного экземпляра будет иметь вид: instance (<em>cx</em>, <em>cx′</em>) => <em>C<sub>i</sub></em> (<em>T</em> <em>u<sub>1</sub></em> … <em>u<sub>k</sub></em>) where { <em>d</em> } [...]

Это означает, что ограничения класса автоматически распределяются по параметрам типа.

Как объяснено в разделеBounded:

Введение класса 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 равен.

...