Gõ suy luận + quá tải


9

Tôi đang tìm kiếm một thuật toán suy luận kiểu cho một ngôn ngữ tôi đang phát triển, nhưng tôi không thể tìm thấy một thuật toán phù hợp với nhu cầu của mình vì chúng thường là:

  • à la Haskell, với tính đa hình nhưng không quá tải ad-hoc
  • à la C ++ (tự động) trong đó bạn có quá tải ad-hoc nhưng các chức năng là đơn hình

Cụ thể, hệ thống loại của tôi là (đơn giản hóa) (Tôi đang sử dụng cú pháp Haskellish nhưng đây là bất khả tri ngôn ngữ):

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

Và tôi đã có một nhà điều hành * đã có một số quá tải:

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

Vân vân...

Và tôi muốn suy ra các loại có thể cho

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

Thứ nhất là Int, thứ hai Matrix Int.

Ví dụ (không hoạt động):

{-# 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
Điều này dường như không đáp ứng các tiêu chí cho Trao đổi ngăn xếp lý thuyết CS, nhưng có vẻ như bạn đang tìm kiếm một câu trả lời lý thuyết hoặc toán học hơn. Tôi nghĩ rằng Khoa học Máy tính có thể thích hợp cho việc này. Vì bạn đã yêu cầu một động thái để có câu trả lời tốt hơn, tôi sẽ gửi nó đến nơi có khả năng được đón nhận.
Thomas Owens

Câu trả lời:


9

Tôi sẽ đề nghị xem xét luận án của Geoffrey Seward Smith

Như bạn có thể đã biết, cách thức hoạt động của các thuật toán suy luận loại phổ biến là chúng đi qua cây cú pháp và với mỗi biểu thức con, chúng tạo ra một ràng buộc kiểu. Sau đó, họ thực hiện các ràng buộc này, giả định kết hợp giữa chúng và giải quyết chúng (thường tìm kiếm một giải pháp chung nhất).

Khi bạn cũng bị quá tải, khi phân tích một toán tử bị quá tải, bạn tạo ra một số ràng buộc kiểu, thay vì một và giả định sự khác biệt giữa chúng, nếu quá tải bị chặn. Bởi vì về cơ bản, bạn đang nói rằng toán tử có thể có `` cái này hoặc cái này hoặc loại kia. "Nếu nó không bị ràng buộc, người ta cần phải sử dụng định lượng phổ quát, giống như với các loại đa hình, nhưng với các ràng buộc bổ sung ràng buộc thực tế Các loại quá tải. Bài báo tôi tham khảo bao gồm các chủ đề này sâu hơn.


Cảm ơn bạn rất nhiều, đây là câu trả lời tôi đang tìm kiếm
miniBill

7

Thật kỳ lạ, bản thân Haskell hoàn toàn gần như có khả năng làm gương của bạn; Hindley-Milner hoàn toàn ổn với tình trạng quá tải, miễn là nó bị ràng buộc tốt:

{-# 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

Bạn đã hoàn tất! Vâng, ngoại trừ việc bạn cần mặc định. Nếu ngôn ngữ của bạn cho phép mặc định Timeslớp thành Int(và sau đó Double), thì các ví dụ của bạn sẽ hoạt động chính xác như đã nêu. Một cách khác để sửa chữa nó, tất nhiên, là để không tự động thúc đẩy Intđể Double, hoặc chỉ làm điều đó khi ngay lập tức cần thiết, và để sử dụng Intliterals như Intchỉ (một lần nữa, đẩy mạnh chỉ khi ngay lập tức cần thiết); giải pháp này cũng sẽ làm việc.


2
Cảm ơn rât nhiều! (mặc dù số lượng tiện ích mở rộng hơn
9 nghìn

1
Không hoạt động ideone.com/s9rSi7
miniBill

1
đó không phải là vấn đề mặc định: ideone.com/LrfEjX
miniBill

1
Ồ, xin lỗi, tôi đã hiểu lầm bạn rồi. Chà, tôi không muốn mặc định (tôi nghĩ vậy) ..
miniBill

2
Bạn có thể thử tạo một ví dụ biên dịch không?
miniBill
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.