防止相互递归的默认方法在运行时循环

Cli*_*ton 7 haskell typeclass

我目前有一个如下结构:

class F a where
   f :: ...
   default f :: (G a...) => ...
   f = (some definition in terms of g)

class F a => G a where
   g :: ...
   default g :: (C a...) => ...
   g = (some definition in terms of f)
Run Code Online (Sandbox Code Playgroud)

在希望有些简单的英语,我可以写f在以下方面g始终.我可以写g来讲f有时,即当a满足一个C约束.

我在这里看到的问题是,如果有人写作,比如说T满意的类型C T

instance F T
instance G T
Run Code Online (Sandbox Code Playgroud)

这将在运行时编译和循环.虽然两个默认定义都是正确的,但重要的是至少定义了一个.

我可以用一个MINIMALpragma 来解决这个问题,如果f并且g在同一个类中,但在这种情况下它们不是.

同时将两者fg在同一个班似乎并不可能,因为同时存在的定义f为每一个定义g,没有的定义g为每一个定义f.一种可能性是g进入F但也对其施加C a约束,但这将阻止我g用任何a不满足的非默认定义来定义C a.

有没有办法重组这个来解决我面临的这种困境?

leh*_*ins 0

我之前的回答是无稽之谈,所以这里有一个(希望)更好的答案。这至少会在编译时给你一个警告。技巧是如果两者都有和 的实例,则在类中实现f'或,但前提是的实例不可能。gGaFGfG

{-# LANGUAGE DefaultSignatures #-}

class C a where

class F a where
  f :: a -> a
  default f :: (G a) => a -> a
  f = g

class F a => G a where
  {-# MINIMAL (f'|g) #-}

  f' :: a -> a
  f' = f

  g :: a -> a
  default g :: (C a) => a -> a
  g = f'

instance F Integer where
  f = succ

instance F Int
instance G Int where
  g = succ

instance C Float
instance F Float
instance G Float where
  f' = succ

-- This will give a compile time warning, but will still
-- loop at runtime:
instance C Double
instance F Double
instance G Double
Run Code Online (Sandbox Code Playgroud)