类型推断+重载


9

我正在寻找一种针对我正在开发的语言的类型推断算法,但找不到适合我需求的语言,因为它们通常是:

  • Haskellà具有多态性,但没有临时重载
  • àla C ++(自动),其中有特定的重载,但函数是单态的

特别是我的类型系统是(简化)(我使用的是Haskellish语法,但这与语言无关):

data Type = Int | Double | Matrix Type | Function Type Type

而且我有一个运算符*,其中有很多重载:

Int -> Int -> Int
(Function Int Int) -> Int -> Int
Int -> (Function Int Int) -> (Function Int Int)
(Function Int Int) -> (Function Int Int) -> (Function Int Int)
Int -> Matrix Int -> Matrix Int
Matrix Int -> Matrix Int -> Matrix Int
(Function (Matrix Int) (Matrix Int)) -> Matrix Int -> Matrix Int

等等...

我想推断出可能的类型

(2*(x => 2*x))*6
(2*(x => 2*x))*{{1,2},{3,4}}

第一个是Int,第二个Matrix Int

示例(不起作用):

{-# LANGUAGE OverlappingInstances, MultiParamTypeClasses,
  FunctionalDependencies, FlexibleContexts,
  FlexibleInstances, UndecidableInstances #-}

import qualified Prelude
import Prelude hiding ((+), (*))
import qualified Prelude

newtype WInt = WInt { unwrap :: Int }

liftW f a b = WInt $ f (unwrap a) (unwrap b)

class Times a b c | a b -> c where
(*) :: a -> b -> c

instance Times WInt WInt WInt where
(*) = liftW (Prelude.*)

instance (Times a b c) => Times a (r -> b) (r -> c) where
x * g = \v -> x * g v

instance Times (a -> b) a b where
f * y = f y

two = WInt 2
six = WInt 6

test :: WInt
test = (two*(\x -> two*x))*six

main = undefined

3
这似乎不符合CS Theory Stack Exchange的标准,但看起来确实在寻找更数学或理论上的答案。我认为计算机科学可能适用于此。由于您请求采取行动以获得更好的答案,因此,我会将其发送到可能会受到广泛欢迎的地方。
Thomas Owens 2014年

Answers:


9

我建议看看杰弗里·苏厄德·史密斯的论文

您可能已经知道,通用类型推断算法的工作方式是遍历语法树,并为每个子表达式生成一个类型约束。然后,他们接受此约束,假定它们之间存在合点,然后加以解决(通常是寻找最通用的解决方案)。

当您还有重载时,在分析重载的运算符时,您将生成多个类型约束,而不是一个类型约束,并且如果重载是有界的,则假定它们之间是析取的。因为您本质上是在说运算符可以具有“此,该,该或该类型”。如果它是无穷大的,则需要诉诸于通用量化,就像多态类型一样,但是还有其他约束实际的我引用的论文更深入地讨论了这些主题。


非常感谢您,这是我一直在寻找的答案
miniBill

7

奇怪的是,哈斯克尔本身就是完美 几乎能够你的榜样的; Hindley-Milner可以很好地处理重载,只要它有界即可:

{-# LANGUAGE OverlappingInstances, MultiParamTypeClasses,
             FunctionalDependencies, FlexibleContexts,
             FlexibleInstances #-}
import Prelude hiding ((*))

class Times a b c | a b -> c where
    (*) :: a -> b -> c

instance Times Int Int Int where
    (*) = (Prelude.*)

instance Times Double Double Double where
    (*) = (Prelude.*)

instance (Times a b c) => Times (r -> a) (r -> b) (r -> c) where
    f * g = \v -> f v * g v

instance (Times a b c) => Times a (r -> b) (r -> c) where
    x * g = \v -> x * g v

instance (Times a b c) => Times (r -> a) b (r -> c) where
    f * y = \v -> f v * y

type Matrix a = (Int, Int) -> a

你完成了!好吧,除了您需要默认设置。如果您的语言允许将Times类默认设置为Int(然后是Double),则您的示例将完全按照说明运行。当然,解决该问题的另一种方法是不自动Int升级为Double或仅在紧迫需要时才执行此操作,而不要只使用Int文字Int(同样,仅在紧迫需要时才进行升级);此解决方案也将起作用。


2
非常感谢你!(尽管扩展数量超过9k)
miniBill 2014年


1
这不是默认问题:ideone.com/LrfEjX
miniBill 2014年

1
哦,对不起,那我误会了你。好了,我不想违约(我认为)..
miniBill

2
您能否尝试产生一个可以编译的示例?
miniBill 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.