{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE TypeOperators         #-}
{-# LANGUAGE TypeFamilies          #-}

module Test3 where


class Fam a where
  from :: a -> PF a

type family PF a


data K r = K r
data (a :*: b) = a :*: b

class HEq a where
  heq :: a -> Bool

instance (HEq a) => HEq (K a) where
  heq (K x) = heq x

instance (HEq a, HEq b) => HEq (a :*: b) where
  heq (x :*: y) = heq x && heq y


{-# INLINABLE eq #-}
eq :: (Fam a, HEq (PF a)) => a -> Bool
eq = heq . from

data Tree = Bin Tree Tree

tree :: Tree
-- |tree = undefined| compiles both with 7.0 and 7.1
tree = treeN 0 where
  treeN 0 = undefined
  treeN n = Bin (treeN 0)     (treeN 0)
  -- Replacing the line above with the line below makes 7.0 loop
  -- treeN n = Bin (treeN (n-1)) (treeN (n-1))

type instance PF Tree = K Tree :*: K Tree

instance Fam Tree where
  from (Bin l r) = K l :*: K r
