Это продолжение моего предыдущего вопроса. Теперь я пытаюсь изменить метод 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
toText
к значению типаa
, поэтому вам нужно ограничение, чтобы доказать, что вы можете это сделать. По сути, вы пытаетесь выполнить эту развертку рекурсивно. - person user2407038   schedule 24.03.2016ToTextC a (Proxy (ToTextHow a))
. - person user2407038   schedule 24.03.2016UndecidableInstances
неплохое расширение. Он просто говорит компилятору снять ограничения, которые накладываются, чтобы гарантировать завершение вывода типа. Поэтому худшее, что может случиться, это то, что когда вы пытаетесь скомпилировать свой код, компилятор застревает в бесконечном цикле вместо того, чтобы получить ошибку типа, говорящую вам, что экземпляр не может быть найден. - person Bakuriu   schedule 24.03.2016