Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 在typeclass定义中添加附加函数/组合符的利弊是什么?_Haskell_Typeclass - Fatal编程技术网

Haskell 在typeclass定义中添加附加函数/组合符的利弊是什么?

Haskell 在typeclass定义中添加附加函数/组合符的利弊是什么?,haskell,typeclass,Haskell,Typeclass,查看以下内容: 在其他地方: (>>) :: forall a b. m a -> m b -> m b {-# INLINE (>>) #-} m >> k = m >>= \_ -> k 通过这种方式,定制的>可以在单子上实现,在单子上可以比通过m>=\\\\\uk>更高效、更自然地实现,但默认实现仍然存在。据我所知,包含“额外”功能的主要原因有两个: 效率:有时会存在效率低下的泛型实现,类的作者希

查看以下内容:

在其他地方:

(>>)        :: forall a b. m a -> m b -> m b
{-# INLINE (>>) #-}
m >> k      = m >>= \_ -> k

通过这种方式,定制的
>
可以在单子上实现,在单子上可以比通过
m>=\\\\\uk>
更高效、更自然地实现,但默认实现仍然存在。

据我所知,包含“额外”功能的主要原因有两个:

  • 效率:有时会存在效率低下的泛型实现,类的作者希望特定于实例的实现会明显更好。在这种情况下,将函数包含在带有默认实现的类中意味着实例可以根据需要使用优化版本,但不需要这样做。有关这方面的有趣示例,请查看
    可折叠
    。这同样适用于
    Monad

  • 实现选择:通常可以使用几个类函数子集;包括所有可能的函数,并根据彼此使用默认实现,这意味着实例可以选择一些函数来实现,并自动获取其余的函数。这也适用于可折叠的
    Eq
    ,但
    Eq
    是一个更简单的示例


    • 将方法包括在typeclass中的另一个论点是,它们何时应该满足某些定律,或者何时能够使这些定律的陈述更清晰。我认为法律在道德上应该与typeclass相关联(“为了声明这个类的实例,我必须提供什么?”),例如,你可能更喜欢用
      返回
      连接
      fmap
      ,而不是
      返回
      =
      )来陈述monad法律;这鼓励您将所有四个运算符都放在type类中(并使
      Monad
      成为
      Functor
      !)的子类),并根据
      join
      给出
      =
      的默认定义,反之亦然。`

      您能列出缺点吗?@TikhonJelvis:老实说,我不确定客观上有什么不利因素。它可以说有点混淆了类的本质,可能会扩大GHC内部使用的类字典,但是如果有任何明显的、彻底的缺点,我不知道。我也是这么想的。但这很奇怪,因为据我所知,这些默认实现很少被使用。@C.A.McCann我想说,在一个类中包含更多方法的缺点是它可能会减少可能的实现数量;e、 g.
      Monoid
      是一个很好的类型类,
      Semigroup
      也是。(当然,这不适用于组合方法——只适用于在概念上不同于其他任何方法的方法。)@DanielWagner:当然,但这里只讨论这种组合方法,不考虑问题的上下文,我的回答中肯定不清楚这一点。。。
      class  Monad m  where
          (>>=)       :: forall a b. m a -> (a -> m b) -> m b
      
          return      :: a -> m a
          fail        :: String -> m a
      
          fail s      = error s
      
      (>>)        :: forall a b. m a -> m b -> m b
      {-# INLINE (>>) #-}
      m >> k      = m >>= \_ -> k