Tip çıkarımı + aşırı yükleme


9

Geliştirdiğim bir dil için bir tür çıkarım algoritması arıyorum, ancak genellikle ikisi de olduğundan, ihtiyaçlarıma uygun olanı bulamadım:

  • à la Haskell, polimorfizm ile ancak geçici aşırı yüklenme yok
  • à la C ++ (otomatik), aşırı yüklemeye sahipsiniz ancak işlevler monomorfiktir

Özellikle benim tip sistem (basitleştiriyor) (Haskellish sözdizimi kullanıyorum ama bu dil agnostik):

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

Ve aşırı yükleri olan bir operatöre * sahibim:

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

Vb...

Ve olası türleri çıkarmak istiyorum

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

Birincisi Int, ikincisidir Matrix Int.

Örnek (işe yaramaz):

{-# 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
Bu, CS Teorisi Stack Exchange kriterlerini karşılamıyor gibi görünüyor, ancak daha matematiksel veya teorik bir cevap arıyorsunuz gibi görünüyor. Bilgisayar Bilimi'nin buna uygun olabileceğini düşünüyorum. Daha iyi yanıtlar almak için bir hamle talep ettiğiniz için, iyi karşılanma olasılığı yüksek olan yere göndereceğim.
Thomas Owens

Yanıtlar:


9

Geoffrey Seward Smith'in tezine bakmanızı öneririm

Muhtemelen bildiğiniz gibi, ortak tür çıkarım algoritmalarının çalışma şekli, sözdizimi ağacından geçmeleri ve her alt ifade için bir tür kısıtlaması oluşturmalarıdır. Daha sonra, bu kısıtlamaları alırlar, aralarında birlikte olduğunu varsayarlar ve çözerler (tipik olarak en genel bir çözüm ararlar).

Aşırı yüklemeye sahip olduğunuzda, aşırı yüklenmiş bir operatörü analiz ederken, bir yerine birkaç tip kısıtlaması üretiyorsunuz ve aşırı yükleme sınırlandırılmışsa aralarında bir kopukluk olduğunu varsayıyorsunuz. Esasen operatörün `` ya bu ya da bu ya da bu tip '' olabileceğini söylüyorsunuz. Eğer sınırsızsa, polimorfik tiplerde olduğu gibi, ancak gerçekleri kısıtlayan ek kısıtlamalarla evrensel nicelemeye başvurmak gerekir. Referans verdiğim kağıt bu konuları daha derinlemesine ele alıyor.


Çok teşekkür ederim, aradığım cevap bu
miniBill

7

Garip, Haskell kendisi mükemmel neredeyse sizin örnek yeteneğine; Hindley-Milner, iyi sınırlanmış olduğu sürece aşırı yükleme ile tamamen iyi:

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

Sen bittin! Bunun dışında, varsayılana ihtiyacınız var. Diliniz Timessınıfı varsayılan Int(ve sonra Double) olarak ayarlamaya izin veriyorsa , örnekleriniz tam olarak belirtildiği gibi çalışır. Başka yolu, tabii ki, otomatik olarak teşvik getirmemektir düzeltmek için Intiçin Doubleveya zaman hemen gerekli sadece bunu yapmak, ve kullanımı Intolarak değişmezleri Int(yalnızca hemen gerekli teşvik, tekrar) sadece; bu çözüm de işe yarayacaktır.


2
Çok teşekkür ederim! (uzantı sayısı 9 binin üzerinde olmasına rağmen)
miniBill

1
Çalışmaz ideone.com/s9rSi7
miniBill

1
bu varsayılan bir sorun değil: ideone.com/LrfEjX
miniBill

1
Üzgünüm, o zaman seni yanlış anladım. Ben varsayılan (sanırım) istemiyorum ..
miniBill

2
Derleyen bir örnek üretmeye çalışabilir misiniz?
miniBill
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.