问题
我希望能够创建 2 data types
:A
并B
创建 2 个函数f
:
f :: A -> Int -> Int
f :: B -> String -> String -> String
我能做到的唯一方法(据我所知)是使用type classes
and instances
。
问题是,我不想显式写f
签名 - 我希望类型检查器为我推断它。可能吗?
示例代码
{-# 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
解释
我正在编写自定义域语言编译器,因此我正在生成 Haskell 代码。我不希望我的语言的最终用户编写显式类型,所以我想尽可能使用 Haskells 强大的类型系统来推断。
如果我像这样编写函数,f2 _ s1 s2 = "test"++s1++s2
则不必显式编写其签名-因为编译器可以推断出它。我们可以以某种方式要求编译器推断上述示例中的签名吗?f
我很想知道解决这个问题的所有可能的“hack”,即使这个 hack 会“丑陋”,因为我正在生成 Haskell 代码,它不一定是“漂亮的”。