3

在上周,我一直在尝试掌握 Haskell 的一些“核心”类型和类型类(但总共学习 Haskell 最多两周),我发现了一些让我烦恼的东西:

  • “Semigroupoid”是“Category”的概括,这意味着任何类别都是平凡的 Semigroupoid,只需忽略它自己的身份并定义

o = (.)

  • 同样,“半群”是“Monoid”的概括,其含义与上述完全相同:只需忽略 mempty 并定义

(<>) = mappend

仅这两个事实,以及 Semigroupoids 和 Semigroups 都只有组合元素的概念(semigroupoid-composition vs semigroup-multiplication)并且 Category 和 Monoid 都具有“统一”(identity vs unit element)的概念带来了请注意,可以将 Semigroupoids 和 Semigroups 以及 Categories 和 Monoids 之间的关系表达如下

import Prelude hiding (id, (.))

import Data.Semigroupoid
import Data.Semigroup

import Control.Category
import Data.Monoid

instance Semigroupoid c => Semigroup (c a a) where
    (<>) = o

instance Category c => Monoid (c a a) where
    mempty = id
    mappend = (.)

main = putStrLn "Does not type-check!"

现在,我不确定为什么它不能编译;ghc 编译器说:

All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.

但碰巧包括

{-# LANGUAGE FlexibleInstances #-}

在文件的顶部修复了所有问题。

上面表达的关系似乎没有在库中构建,而 Semigroupoid 和 Category 之间以及 Semigroup 和 Monoid 之间的关系是内置的。

有什么具体原因吗,我只是想念它吗?

也许它与神秘的“FlexibleInstances”有关?

任何见解将不胜感激。

4

1 回答 1

3

如果它只需要FlexibleInstances没有人会介意(该扩展是完全无害的),但不幸的是,一旦您添加了足够有趣的其他实例,它也会导致需要一个非常无害的其他扩展。即,

{-# LANGUAGE FlexibleInstances #-}

import Control.Category (Category)

instance Category c => Monoid (c a a)

data Nontrivial s q = Nontrivial {
      someLabel :: String
    , someValues :: [(s, Int)]
    , otherValues :: Maybe (String, q)
    , moreStuff :: ({-...-})
    }

instance (Monoid s, Monoid q) => Monoid (Nontrivial s q) where
  mempty = Nontrivial "" [] Nothing ()

main = case mempty :: Nontrivial String String of
  Nontrivial _ _ _ _ -> return ()

不编译:

$ runhaskell  wtmpf-file6064.hs 

wtmpf-file6064.hs:17:13:
    Overlapping instances for Monoid (Nontrivial String String)
      arising from a use of ‘mempty’
    Matching instances:
      instance Category c => Monoid (c a a)
        -- Defined at wtmpf-file6064.hs:5:10
      instance (Monoid s, Monoid q) => Monoid (Nontrivial s q)
        -- Defined at wtmpf-file6064.hs:14:10
    In the expression: mempty :: Nontrivial String String
    In the expression:
      case mempty :: Nontrivial String String of {
        Nontrivial _ _ _ _ -> return () }
    In an equation for ‘main’:
        main
          = case mempty :: Nontrivial String String of {
              Nontrivial _ _ _ _ -> return () }

现在,您可以通过添加{-# OVERLAPPABLE #-}Pragmas使其工作,但这是一些相当繁琐的事情,可能会导致奇怪的行为。强烈避免此类情况。

于 2017-02-26T12:08:35.070 回答