Перегрузка метода show для типов Maybe

Это продолжение моего предыдущего вопроса. Теперь я пытаюсь изменить метод toText, чтобы он также обрабатывал Maybe a с перегруженной функцией toText. Ниже приведен код, который компилируется и работает нормально — теперь я хотел бы перегрузить toText для Maybe a, используя само определение toText для других типов:

{-# LANGUAGE TypeFamilies, DataKinds, MultiParamTypeClasses, FlexibleInstances, ScopedTypeVariables, FlexibleContexts #-}

import Data.List
import Data.Text (unpack, pack, Text, empty)
import Data.Proxy
import Data.Maybe (maybe)

data ToTextMethod = TTMText | TTMShow | TTMMaybe

type family ToTextHow a where
     ToTextHow Text = TTMText
     ToTextHow (Maybe b) = TTMMaybe
     ToTextHow a = TTMShow

class ToTextC a b where
      toTextC :: a -> b -> Text

instance Show a => ToTextC a (Proxy TTMShow) where
      toTextC a _ = pack (show a)

instance Show a => ToTextC (Maybe a) (Proxy TTMMaybe) where
      -- Will like to replace this with
      -- toTextC a _ = maybe empty toText a 
      toTextC a _ = maybe empty (pack . show) a 

instance ToTextC Text (Proxy TTMText) where
      toTextC t _ = t

toText :: forall a. (Show a, ToTextC a (Proxy (ToTextHow a))) => a -> Text
toText x = toTextC x (Proxy :: Proxy (ToTextHow a))

Если я обновлю определение toTextC для типа TTMMaybe, как указано в комментарии ниже:

instance Show a => ToTextC (Maybe a) (Proxy TTMMaybe) where
      toTextC a _ = maybe empty toText a

Я получаю эту ошибку - буду признателен за советы о том, как решить эту перегрузку:

 Could not deduce (ToTextC a (Proxy (ToTextHow a)))
      arising from a use of ‘toText’
    from the context (Show a)
      bound by the instance declaration at Test.hs:21:10-53
    In the second argument of ‘maybe’, namely ‘toText’
    In the expression: maybe empty toText a
    In an equation for ‘toTextC’: toTextC a _ = maybe empty toText a

Обновление 1:

Следуя предложению в комментарии, я исправил его, используя дополнительное ограничение. Однако для этого требовалось включить расширение UndecidableInstances! Есть ли лучший способ сделать это без использования UndecidableInstances? Возможно, какой-то оператор типа или функция для выражения вычислений на уровне типа?

instance (Show a,ToTextC a (Proxy (ToTextHow a))) => ToTextC (Maybe a) (Proxy TTMMaybe) where
      toTextC a _ = maybe empty toText a 

person Sal    schedule 23.03.2016    source источник
comment
Он сообщает вам, что ищет экземпляр - помещение этого экземпляра в контекст заставит его скомпилироваться. Вы пытаетесь рекурсивно применить функцию toText к значению типа a, поэтому вам нужно ограничение, чтобы доказать, что вы можете это сделать. По сути, вы пытаетесь выполнить эту развертку рекурсивно.   -  person user2407038    schedule 24.03.2016
comment
@ user2407038, как бы вы выразили это ограничение?   -  person Sal    schedule 24.03.2016
comment
Ограничение буквально ToTextC a (Proxy (ToTextHow a)).   -  person user2407038    schedule 24.03.2016
comment
Примечание. UndecidableInstances неплохое расширение. Он просто говорит компилятору снять ограничения, которые накладываются, чтобы гарантировать завершение вывода типа. Поэтому худшее, что может случиться, это то, что когда вы пытаетесь скомпилировать свой код, компилятор застревает в бесконечном цикле вместо того, чтобы получить ошибку типа, говорящую вам, что экземпляр не может быть найден.   -  person Bakuriu    schedule 24.03.2016
comment
@Bakuriu, да, вот чего я опасаюсь. Неплохое расширение, но есть возможность не останавливаться. Итак, изучаем, есть ли лучший способ сообщить компилятору о вычислениях на уровне типов.   -  person Sal    schedule 24.03.2016