【问题标题】:How to solve a Haskell code error "<>' is not a (visible) method of class `Monoid'"?如何解决 Haskell 代码错误“<>' is not a (visible) method of class `Monoid'”?
【发布时间】:2020-01-01 07:40:01
【问题描述】:

让我们看看在 Haskell 中用于处理反向列表的新数据类型的声明:

import Data.Monoid 
data RevList a = Nil | RCons (RevList a) a deriving (Eq, Show)

instance Monoid a => Monoid (RevList a) where
    mempty = Nil

instance Semigroup a => Monoid (RevList a) where
    Nil <> RCons (RevList a) a = RCons (RevList a) a
    RCons (RevList a) a <> RNil = RCons (RevList a) a
    Nil <> Nil = Nil

我困扰的问题是编译失败,描述如下:

 `<>' is not a (visible) method of class `Monoid'

首先,我尝试在没有声明任何 Semigroup 实例的情况下创建一个 Monoid 实例,但在阅读 this question 后,它导致了另一个失败的管理。那么,当前的东西中的“”有什么问题呢?可以肯定的是,我知道缺少像 mappend 或 mconcat 这样的 Monoid 函数作为强制添加到 Monoid 实例代码中。

【问题讨论】:

    标签: haskell monoids semigroup


    【解决方案1】:

    定义&lt;&gt; 的实例应该用于Semigroup (RevList a),而不是Monoid (RevList a),因为&lt;&gt;Semigroup 方法。

    我知道缺少像 mappend 或 mconcat 这样的 Monoid 函数作为强制添加到 Monoid 实例代码中

    它们实际上不是强制性的,你可以从

    中看出这一点

    最小的完整定义

    mempty
    

    http://hackage.haskell.org/package/base-4.12.0.0/docs/Data-Monoid.html.

    您实际上也没有在实例中使用约束(=&gt; 之前的部分);例如你没有在mempty :: RevList a 的实现中调用mempty :: a。所以他们可以被删除,你最终得到

    instance Monoid (RevList a) where
        mempty = RNil
    
    instance Semigroup (RevList a) where
        RNil <> RCons (RevList a) a = RCons (RevList a) a
        RCons (RevList a) a <> RNil = RCons (RevList a) a
        RNil <> RNil = RNil
    

    【讨论】:

      【解决方案2】:
      instance Semigroup [a] where
         (<>)  =  (++)
      

      让我们不必定义

      append (x:xs) ys  =  x : append xs ys     -- x is the first
      append    []  ys  =                ys
      

      将相同的常规列表数据类型(x:xs) 视为以x 结尾的反向列表的表示,我们必须定义:

      apprev xs (y:ys)  =  y : apprev xs ys     -- y is the last
      apprev xs    []   =             xs
      

      (实际上,apprev == flip append!——也就是说,我们基本上只是在照镜子。)

      类型是由它的交互定义的,而不是表示。如果旧的数据类型与新的数据类型完全同构(可以很好地表示它),则不需要全新的数据类型定义。只需一个 newtype 标记就足够了,以表明附加上的不同行为:

      newtype RevList a  =  Rev [a]
      
      instance Semigroup (RevList a) where
         Rev xs <> Rev []      =  Rev xs
         Rev xs <> Rev (y:ys)  =  Rev (y:zs) 
                                    where 
                                    Rev zs  =  Rev xs <> Rev ys
      

      (附注:您的定义并未处理所有可能的情况。它还混合了NilRNil。)

      【讨论】:

        猜你喜欢
        • 2013-01-28
        • 2020-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多