2016-05-30 3 views
2

Как часть более крупного проекта, написанного в Haskell, я работаю над небольшой библиотекой утилиты, чтобы инкапсулировать общие парадигмы, которые я использую во всем моем коде. Одна из этих функций (или две функции, а), что я работал на является fromLeft :: Either a b -> a и fromRight :: Either a b -> b, которые представляют собой частичные функции, которые не определены (error быть точными) на анти- киральных конструкторов:Haskell: safe 'show'

fromLeft :: Either a b -> a 
fromLeft x = case x of 
       (Left x) -> x 
       (Right y) -> error "fromLeft: (Right _)" 

fromRight :: Either a b -> b 
fromRight x = case x of 
       (Right x) -> x 
       (Left y) -> error "fromRight: (Left _)" 

В любом случае, я хотел если возможно, продлить эти функции, чтобы, если y во втором шаблоне соответствовали каждой функции, имели тип, который был , он был бы напечатан вместо "_". Тем не менее, нет очевидного способа обойти это без ограничения ограничения в подписи, что сделает эти функции утрачивать свою общность.

Существует ли расширение или модуль voodoo, который может выборочно выполнять функции typeclass для экземпляров этих типов и возвращать общий результат для других типов? Более конкретно, есть ли способ в Haskell, чтобы написать программу, которая имитирует недействительного функцию \x -> if (showable x) then show x else "_"

+3

Возможный дубликат [Проверьте, является ли тип является экземпляром Show в Haskell?] (Http://stackoverflow.com/questions/35785176/check-whether-a-type- is-a-instance-of-show-in-haskell) –

+5

https://wiki.haskell.org/GHC/AdvancedOverlap имеет точные проблемы и решения. Я бы не рекомендовал их реализовать! – ibotty

+0

@ibotty Это выглядит интересно. Спасибо за долю. Я не могу прислушаться к вашему предупреждению: P – archaephyrryx

ответ

4

Как об этом:

fromRightWith :: (a -> String) -> Either a b -> b 
fromRightWith show (Left a) = error $ "fromRight: (Left " ++ show a ++ ")" 
fromRightWith _ (Right b) = b 

fromRight :: Either a b -> b 
fromRight = fromRightWith $ const "_" 

fromRight' :: Show a => Either a b -> b 
fromRight' = fromRightWith show 

Тогда, если в вашем коде, вы знаете, что a является экземпляром Show, использование fromRight'. Если нет, то используйте fromRight:

instance Show MyError where 
    show = -- .. 

trySomething :: IO (Either MyError Value) 
trySomething = --- .. 

main = do 
    value <- fromRight' <$> trySomething 
    -- .. 
+0

Спасибо за этот ответ. Это более или менее то, о чем я думал, но @ibotty предоставил интересный ресурс, который в конечном итоге я использовал (по крайней мере, на данный момент (лучше или хуже). – archaephyrryx

Смежные вопросы