2015-03-16 3 views
3

Есть в любом случае, даже используя причудливое сочетание расширений GHC, сделать функцию h как следующий psudeocode:Выберите функцию, основанную на классе

f :: (C1 a) => a -> Int 
g :: (C2 a) => a -> Int 

h x = 
    if (isOfClass C1 x) then (f x) 
    else if (isOfClass C2 x) then (g x) 
    else COMPILE_ERROR 

Обратите внимание, что если x является оба класса C1 и C2 я не Не возражаете, если я получаю противоречивое поведение в зависимости от того, что в сфере видимости.

+1

У вас есть случай использования? – Koterpillar

ответ

3

Wrap значение другого типа, например Either или пользовательский тип

Пример с Either:

h :: (C1 a, C2 b) => Either a b -> Int 
h = either f g 
3

Это невозможно, так как он будет справляться с раздельной компиляции. Рассмотрим

module A where 

data A = A Int 

isOfClassEq :: a -> Bool 
isOfClassEq = <<some magic here>> 

test :: Bool 
test = isOfClassEq (A 42) 

и

module Main where 
import A 
instance Eq A where (A x) == (A y) = x == y 
main = print test 

Если я открыл модуль A в GHCi, test будет вычисляться False. Таким образом, код, связанный с test, должен вернуть False. Вместо этого, если я загружаю модуль Main и запускаю main, я должен увидеть True. Если у нас есть отдельная компиляция, так как компилятор не может знать о экземпляре при компиляции модуля A, он должен сгенерировать код для test, который проверяет членство класса во время выполнения.

Для этого необходимо, чтобы GHC поддерживал runtime всю информацию о типе, включая тип таблицы < -> для выполнения проверок. Однако Haskell разработан таким образом, что информация о типе может быть отброшена во время компиляции.

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