簡體   English   中英

為什么我的 Semigroup/Monoid 實例重疊?

[英]Why is my Semigroup/Monoid instance overlapping?

我正在嘗試實現一種延遲構造非確定性有限自動機 (NFA) 的方法。 幾年前在 F# 中做過這件事,現在想在利用Monoid類型類的同時嘗試使用 Haskell。

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

module NFA where

data State = State Match State | Split State State | Final deriving (Show)
data Match = Any | Char Char | ... deriving (Show)

type StateF = State -> State

complete :: StateF -> State -> State
complete statef exit = statef exit

connect :: StateF -> StateF -> StateF
connect fst snd = complete fst . complete snd

empty :: StateF
empty = id

instance Semigroup StateF where
  (<>) = connect

instance Monoid StateF where
  mempty = empty

此代碼無法編譯,因為我的SemigroupMonoid實例與來自GHC.Base的實例 Semigroup b => Semigroup (a instance Semigroup b => Semigroup (a -> b)instance Monoid b => Monoid (a -> b)重疊,但我不這樣做不明白為什么。

我看到函數a -> b上有一個Monoid實例,其中bMonoid本身。 但是State沒有Monoid實例,那么StateF ( State -> State ) 怎么重疊呢?

是因為有人可能會在其他地方為State實現Monoid嗎?

另外,我該如何解決這個問題?

我知道 a 可以將StateF定義為...

data StateF = StateF (State -> State)

...但這也會在模式匹配和構造StateF時增加語法噪音。

編譯器錯誤:

src\NFA.hs:10:10: error:
    * Overlapping instances for Semigroup StateF
        arising from a use of `GHC.Base.$dmsconcat'
      Matching instances:
        instance Semigroup b => Semigroup (a -> b) -- Defined in `GHC.Base'
        instance Semigroup StateF -- Defined at src\NFA.hs:10:10
    * In the expression: GHC.Base.$dmsconcat @(StateF)
      In an equation for `GHC.Base.sconcat':
          GHC.Base.sconcat = GHC.Base.$dmsconcat @(StateF)
      In the instance declaration for `Semigroup StateF'
   |
10 | instance Semigroup StateF where
   |          ^^^^^^^^^^^^^^^^

src\NFA.hs:10:10: error:
    * Overlapping instances for Semigroup StateF
        arising from a use of `GHC.Base.$dmstimes'
      Matching instances:
        instance Semigroup b => Semigroup (a -> b) -- Defined in `GHC.Base'
        instance Semigroup StateF -- Defined at src\NFA.hs:10:10
    * In the expression: GHC.Base.$dmstimes @(StateF)
      In an equation for `GHC.Base.stimes':
          GHC.Base.stimes = GHC.Base.$dmstimes @(StateF)
      In the instance declaration for `Semigroup StateF'
   |
10 | instance Semigroup StateF where
   |          ^^^^^^^^^^^^^^^^

src\NFA.hs:13:10: error:
    * Overlapping instances for Semigroup StateF
        arising from the superclasses of an instance declaration
      Matching instances:
        instance Semigroup b => Semigroup (a -> b) -- Defined in `GHC.Base'
        instance Semigroup StateF -- Defined at src\NFA.hs:10:10
    * In the instance declaration for `Monoid StateF'
   |
13 | instance Monoid StateF where
   |          ^^^^^^^^^^^^^

src\NFA.hs:13:10: error:
    * Overlapping instances for Monoid StateF
        arising from a use of `GHC.Base.$dmmappend'
      Matching instances:
        instance Monoid b => Monoid (a -> b) -- Defined in `GHC.Base'
        instance Monoid StateF -- Defined at src\NFA.hs:13:10
    * In the expression: GHC.Base.$dmmappend @(StateF)
      In an equation for `mappend':
          mappend = GHC.Base.$dmmappend @(StateF)
      In the instance declaration for `Monoid StateF'
   |
13 | instance Monoid StateF where
   |          ^^^^^^^^^^^^^

src\NFA.hs:13:10: error:
    * Overlapping instances for Monoid StateF
        arising from a use of `GHC.Base.$dmmconcat'
      Matching instances:
        instance Monoid b => Monoid (a -> b) -- Defined in `GHC.Base'
        instance Monoid StateF -- Defined at src\NFA.hs:13:10
    * In the expression: GHC.Base.$dmmconcat @(StateF)
      In an equation for `mconcat':
          mconcat = GHC.Base.$dmmconcat @(StateF)
      In the instance declaration for `Monoid StateF'
   |
13 | instance Monoid StateF where
   |          ^^^^^^^^^^^^^

至少對於顯示的代碼,將StateF從類型別名更改為新類型newtype引入最小的更改並且沒有運行時開銷。

module NFA where

data State = State Match State | Split State State | Final deriving (Show)
data Match = Any | Char Char | ... deriving (Show)

newtype StateF = StateF (State -> State)

-- This is one change
complete :: StateF -> State -> State
complete (StateF f) = f

connect :: StateF -> StateF -> StateF
connect fst snd = complete fst . complete snd

-- This is the other
empty :: StateF
empty = StateF id

instance Semigroup StateF where
  (<>) = connect

instance Monoid StateF where
  mempty = empty

如果你使用記錄語法,你甚至不需要模式匹配來complete

newtype StateF  = StateF { runStateF :: State -> State }

complete :: StateF -> State -> State
-- complete statef exit = runStateF statef exit
-- complete statef = runStateF statef
complete = runStateF

(不要將complete視為實際狀態轉換器應用於狀態,而是提取狀態轉換器以便將其應用於狀態。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM