ПроблемуТип вывода экземпляра функции
Я хочу, чтобы иметь возможность создать 2 data types
: A
и B
и создать 2 функции f
:
f :: A -> Int -> Int
f :: B -> String -> String -> String
Единственный w Я могу это сделать (насколько я знаю) использовать type classes
и instances
.
Проблема в том, что я не хочу явно писать f
подписи - я хочу, чтобы тип checker сделал это для меня. Является ли это возможным?
Пример кода
{-# LANGUAGE FlexibleInstances, FunctionalDependencies, UndecidableInstances #-}
data A = A{ax::Int} deriving(Show)
data B = B{bx::Int} deriving(Show)
data C = C{cx::Int} deriving(Show)
-- I don't want to explicit say the signature is Int->Int
-- I would love to write:
-- instance Func_f A (a->b) where
instance Func_f A (Int->Int) where
f _ i = i*2
-- I don't want to explicit say the signature is String->String->String
-- I would love to write:
-- instance Func_f B (a->b->c) where
instance Func_f B (String->String->String) where
f _ s1 s2 = "test"++s1++s2
-- I don't want to explicit say the signature is a->a
-- I would love to write:
-- instance Func_f C (a->b) where
instance Func_f C (a->a) where
f _ i = i
class Func_f a b | a -> b where
f :: a -> b
f2 _ s1 s2 = "test"++s1++s2 -- Here the type inferencer automaticly recognizes the signature
main :: IO()
main = do
let
a = A 1
b = B 2
c = C 3
a_out = f a 5
b_out = f b "a" "b"
c_out = c 6
print a_out
print b_out
print c_out
Explaination
Я пишу компилятор языка пользовательского домена и я генерации Haskell кода в качестве результата. Я не хочу, чтобы конечные пользователи моего языка пишут явные типы, поэтому я хочу использовать мощную систему типов Haskells, чтобы вывести как можно больше.
Если я пишу функцию, как f2 _ s1 s2 = "test"++s1++s2
, я делаю , а не должен явно писать свою подпись - потому что компилятор может ее вывести. Можем ли мы каким-то образом попросить компилятор вывести подписи f
в приведенном выше примере?
Я хотел бы знать все возможные «взломы», чтобы решить эту проблему, даже если этот хак будет «уродливым», потому что я генерирую код Haskell, и он не должен быть «красивым».
Невозможно (что я знаю) указать тип параметра класса типа, выведенного из данной реализации класса. Это может быть сложно, так как ваш первый пример может быть выведен для того, чтобы иметь тип 'f :: (Num a) => A -> a -> a'. Будет ли какая-либо из реализаций 'f' использовать первый аргумент или просто используется, чтобы определить, какую версию' f' использовать? – sabauma
@sabauma - я знаю это - но я действительно не хочу делать очень подробный тип типа 'Int-> Int' - я был бы счастлив, если бы Haskell вывел бы его как' f :: (Num a) => A -> a -> a' или что-то еще - если я могу позже использовать его (если это возможно). Иногда можно использовать первый аргумент - вы можете думать об этом как «это» в императивных языках. –
@sabauma - я отредактировал пример - просмотрите комментарии. –