【问题标题】:Relation between the Semigroupoid and Semigroup classesSemigroupoid 和 Semigroup 类之间的关系
【发布时间】:2017-02-26 11:54:44
【问题描述】:

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

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

o = (.)

  • “Semigroup”也是“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”有关?

任何见解将不胜感激。

【问题讨论】:

    标签: haskell category-theory monoids semigroup category-abstractions


    【解决方案1】:

    如果它只需要 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 使其正常工作,但这是一项相当繁琐的工作,可能会导致奇怪的行为。强烈避免此类情况。

    【讨论】:

    • 我不确定我是否理解为什么会发生这种情况:当然(通常)Nontrivial 不是一个类别,但这就是我的观点:任何类别都会自动变成一个幺半群,而 Nontrivial 是一个幺半群只要它的类型参数也是。由于 Nontrivial 不是(被纳入)一个类别,我不明白 ghc 在抱怨什么。
    • 知道Nontrivial不是一个类别。编译器无法知道这一点;事实上,任何人都可以通过稍后定义一个孤儿instance Category Nontrivial使其成为一个类别。当然正确的是,这不可能是格式良好的,因为sq 参数实际上都是协变的,但第一个参数是逆变的要求不是法律Category 类以编译器可以理解的形式明确提及,那么应该以什么理由拒绝该实例的可能性?
    猜你喜欢
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 2011-05-01
    • 2016-09-12
    • 2017-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多