作为一名程序员,最好放弃数学界广泛使用的加性和乘性幺半群的方便符号表示法,而是以更抽象的方式思考幺半群——作为具有独特运算的独特代数结构,这种运算通常与数字环中的加法和乘法无关,其中
Num
类型类可以被认为是一个近似的形式化。Haskell类型系统依赖于您确保相同的名称引用相同的事物,不同的名称引用不同的事物——这个简单而逻辑的规则帮助它避免混淆。这就是为什么任何幺半群的幺半运算通常用菱形符号
<>
表示。
(实际上,由于传统,初始幺半群上的操作有时被表示为++
。)
另外,定义通常数字的Num
很不合逻辑,但被认为是实用的,并且在硬件级别上首先进行定义,然后提取组成幺半群:
base-4.11.1.0:Data.Semigroup.Internal
...
198 instance Num a => Semigroup (Sum a) where
199 (<>) = coerce ((+) :: a -> a -> a)
...
227 instance Num a => Semigroup (Product a) where
228 (<>) = coerce ((*) :: a -> a -> a)
...
— 因此,在任何抽象代数学科出现之前,+
都会被占用。
代数学家的方法 尽管如此,完全可以通过具有两个单子群的类型来定义一个环:
{-# language FlexibleInstances #-}
{-# language FlexibleContexts #-}
{-# language UndecidableInstances #-}
{-# language TypeApplications #-}
module MonoidsField where
import Prelude (Integer, Semigroup, (<>), Monoid, mempty, Show, show)
import Data.Coerce
newtype Sum a = Sum { getSum :: a }
newtype Product a = Product { getProduct :: a }
data N = Z | S { predecessor :: N}
dec :: Coercible a (N -> N) => a
dec = coerce predecessor
instance Show N
where
show Z = ""
show x = '|' : show (predecessor x)
instance Semigroup (Sum N)
where
u <> (Sum Z) = u
u <> v = coerce S (u <> dec v)
instance Monoid (Sum N)
where
mempty = Sum Z
instance Semigroup (Product N)
where
u <> (Product Z) = coerce (mempty @(Sum N))
u <> v = let (*) = (<>) @(Product N)
(+) = coerce ((<>) @(Sum N))
in u + (u * dec v)
instance Monoid (Product N)
where
mempty = Product (S Z)
(+) :: Monoid (Sum a) => a -> a -> a
x + y = getSum (Sum x <> Sum y)
(*) :: Monoid (Product a) => a -> a -> a
x * y = getProduct (Product x <> Product y)
class PseudoRing a
instance (Monoid (Sum a), Monoid (Product a)) => PseudoRing a
where
正如您所看到的,PseudoRing
类本身不添加任何操作,但确保已定义了其需要的两个幺半群。如果您实例化它,则意味着您已确保分配公理成立。
正如这个例子所示,子类可以被认为包含其超类定义的所有操作。因此,您可以声明instance Num a => Foo a
并重用+
的定义。然后,您甚至可以为自己的类型定义"partial"Num
实例,这些类型事先不会具有所有所需方法的定义。这种方法显然是不安全、令人困惑且总体上不可取的,但如果加上适当的科学许可证,这可能正是您所需要的。因此,您的示例变为:
class Foo a
instance Num a => Foo a
如果上述内容需要澄清,请告诉我!
Prelude.+
,但这似乎是极其不必要的。为什么Foo
一定要使用加号运算符?如果你只是将它改成独特的东西,所有这些疯狂的事情都会消失 :) - Adam Smith(+)
,其实例将是一个“常规”类型类,为(+)
在其实例中遵守的特定法律提供一组。据我所知,这样的东西并不存在 :) - chepner