Hindley-Milner nedir?


124

Bu Hindley-Milner terimiyle karşılaştım ve ne anlama geldiğini anlayıp anlamadığımdan emin değilim.

Aşağıdaki gönderileri okudum:

Ancak wikipedia'da bu terim için genellikle bana kısa bir açıklama sunan tek bir giriş yoktur.
Not - şimdi bir tane eklendi

Bu ne?
Hangi diller ve araçlar onu uygular veya kullanır?
Lütfen kısa bir cevap verir misiniz?

Yanıtlar:


167

Hindley-Milner, Roger Hindley (mantığa bakan) ve daha sonra Robin Milner (programlama dillerine bakan) tarafından bağımsız olarak keşfedilen bir tip sistemdir . Hindley-Milner'ın avantajları

  • Polimorfik işlevleri destekler ; örneğin, öğelerin türünden bağımsız olarak size listenin uzunluğunu verebilen bir işlev veya ağaçta depolanan anahtarların türünden bağımsız olarak ikili ağaç araması yapan bir işlev.

  • Bazen , uzunluk işlevi örneğinde olduğu gibi, bir işlev veya değer birden fazla türe sahip olabilir : "tamsayıdan tamsayıya kadar dizelerin listesi", "tamsayıya çiftlerin listesi" vb. Olabilir. üzerinde. Bu durumda, Hindley-Milner sisteminin bir sinyal avantajı, iyi yazılmış her terimin ana tür olarak adlandırılan benzersiz bir "en iyi" türe sahip olmasıdır . Liste uzunluğu işlevinin ana türü "herhangi bir aişlev için, listeden atamsayıya" şeklindedir. Burada a, lambda analizinde açık olan, ancak çoğu programlama dilinde örtük olan bir "tür parametresi" bulunmaktadır . parametrik polimorfizmde . (ML'de uzunluk işlevinin bir tanımını yazarsanız, tür parametresini şu şekilde görebilirsiniz:

     fun 'a length []      = 0
       | 'a length (x::xs) = 1 + length xs
    
  • Eğer bir terim Hindley-Milner türü vardır, o zaman ana tip herhangi bir türü bildirimleri gerektirmeden anlaşılabilir programcı tarafından ya da diğer ek açıklamalar. (Bu karışık bir lütuftur, çünkü herhangi bir ek açıklama olmadan büyük bir ML kodu yığınını kimin işlediğini herkes doğrulayabilir.)

Hindley-Milner, statik olarak yazılmış neredeyse her işlevsel dilin tür sisteminin temelidir. Yaygın olarak kullanılan bu tür diller şunları içerir:

Tüm bu diller Hindley-Milner'ı genişletmiştir; Haskell, Clean ve Objective Caml bunu iddialı ve alışılmadık şekillerde yapıyor. (Temel Hindley-Milner, örneğin, belirtilmemiş tipte değerlerin bir listesini tutan değiştirilebilir bir hücre kullanılarak tersine çevrilebileceğinden, uzantılar değişken değişkenlerle başa çıkmak için gereklidir. Bu tür sorunlar, değer kısıtlaması adı verilen bir uzantı tarafından ele alınır .)

Yazılmış işlevsel dillere dayanan diğer birçok küçük dil ve araç Hindley-Milner'ı kullanır.

Hindley-Milner, daha fazla türe izin veren ancak programcı tarafından ek açıklamalar gerektiren bir Sistem F kısıtlamasıdır .


2
@NormanRamsey Bunun kötü bir eski olduğunu biliyorum ama beni sonsuza kadar sinirlendiren şeyi açıklığa kavuşturduğunuz için teşekkürler: Her seferinde birisi tür çıkarımı hakkında konuşurken HM'nin bir tip olup olmadığını sorgulamaya başladığım noktaya işaret ediyor sistem ya da sadece çıkarım algoritması ... Teşekkür ederim, sanırım bu konuda insanları yanlış bilgilendirdiği için wikipedia'da benim kafamı bile karıştırdılar ..
Jimmy Hoffa

1
Neden basitçe polimorfik yerine parametrik olarak polimorfiktir? Herhangi bir vermiş olduğunuz örnek, bunu bir örnek olarak görüyorum polimorfizm - burada tanımda belirtilen süper tip yerine alt tipler kullanılabilir ve parametrik polimorfizm ala C ++ burada gerçek tip programcı tarafından bir oluşturmak için belirlenir yeni işlev.
corazza

1
@jcora: Birkaç yıl geç ama gelecek okuyucuların yararına: denir parametrik nedeniyle özelliğine polimorfizmi parametricity , sen takın her tür gibi bir fonksiyonu tüm örneklerini hangi vasıta length :: forall a. [a] -> Intne olursa olsun aynı davranırlar gerekir a-Bu opak; onun hakkında hiçbir şey bilmiyorsun. Hiçbir var instanceof(Java jenerikler) ne de “ördek yazarak” (C ++ şablonları) ekstra tip kısıtlamaları (Haskell typeclasses) ekleyin sürece. Parametriklikle, bir fonksiyonun tam olarak ne yapıp yapamayacağına dair güzel kanıtlar elde edebilirsiniz.
Jon Purdy

8

Orijinal makaleleri Google Scholar veya CiteSeer - veya yerel üniversite kütüphanenizi kullanarak bulabilirsiniz. İlki, derginin ciltli kopyalarını bulmanız gerekebilecek kadar eski, çevrimiçi olarak bulamadım. Diğeri için bulduğum bağlantı koptu, ancak başkaları da olabilir. Bunlardan alıntı yapan kağıtları kesinlikle bulabileceksiniz.

Hindley, Roger J, Kombinasyon mantığında bir nesnenin ana tip şeması , Amerikan Matematik Derneği İşlemleri, 1969.

Milner, Robin, A Theory of Type Polymorphism , Journal of Computer and System Sciences, 1978.




6

C # 'da basit Hindley-Milner türü çıkarım uygulaması:

(Lisp-ish) S-ifadeleri üzerinden Hindley-Milner türü çıkarım, 650 satırın altında C #

Uygulamanın sadece 270 civarında C # satırı aralığında olduğuna dikkat edin (uygun W algoritması ve bunu destekleyecek birkaç veri yapısı için).

Kullanım alıntı:

    // ...

    var syntax =
        new SExpressionSyntax().
        Include
        (
            // Not-quite-Lisp-indeed; just tolen from our host, C#, as-is
            SExpressionSyntax.Token("\\/\\/.*", SExpressionSyntax.Commenting),
            SExpressionSyntax.Token("false", (token, match) => false),
            SExpressionSyntax.Token("true", (token, match) => true),
            SExpressionSyntax.Token("null", (token, match) => null),

            // Integers (unsigned)
            SExpressionSyntax.Token("[0-9]+", (token, match) => int.Parse(match)),

            // String literals
            SExpressionSyntax.Token("\\\"(\\\\\\n|\\\\t|\\\\n|\\\\r|\\\\\\\"|[^\\\"])*\\\"", (token, match) => match.Substring(1, match.Length - 2)),

            // For identifiers...
            SExpressionSyntax.Token("[\\$_A-Za-z][\\$_0-9A-Za-z\\-]*", SExpressionSyntax.NewSymbol),

            // ... and such
            SExpressionSyntax.Token("[\\!\\&\\|\\<\\=\\>\\+\\-\\*\\/\\%\\:]+", SExpressionSyntax.NewSymbol)
        );

    var system = TypeSystem.Default;
    var env = new Dictionary<string, IType>();

    // Classic
    var @bool = system.NewType(typeof(bool).Name);
    var @int = system.NewType(typeof(int).Name);
    var @string = system.NewType(typeof(string).Name);

    // Generic list of some `item' type : List<item>
    var ItemType = system.NewGeneric();
    var ListType = system.NewType("List", new[] { ItemType });

    // Populate the top level typing environment (aka, the language's "builtins")
    env[@bool.Id] = @bool;
    env[@int.Id] = @int;
    env[@string.Id] = @string;
    env[ListType.Id] = env["nil"] = ListType;

    //...

    Action<object> analyze =
        (ast) =>
        {
            var nodes = (Node[])visitSExpr(ast);
            foreach (var node in nodes)
            {
                try
                {
                    Console.WriteLine();
                    Console.WriteLine("{0} : {1}", node.Id, system.Infer(env, node));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            Console.WriteLine();
            Console.WriteLine("... Done.");
        };

    // Parse some S-expr (in string representation)
    var source =
        syntax.
        Parse
        (@"
            (
                let
                (
                    // Type inference ""playground""

                    // Classic..                        
                    ( id ( ( x ) => x ) ) // identity

                    ( o ( ( f g ) => ( ( x ) => ( f ( g x ) ) ) ) ) // composition

                    ( factorial ( ( n ) => ( if ( > n 0 ) ( * n ( factorial ( - n 1 ) ) ) 1 ) ) )

                    // More interesting..
                    ( fmap (
                        ( f l ) =>
                        ( if ( empty l )
                            ( : ( f ( head l ) ) ( fmap f ( tail l ) ) )
                            nil
                        )
                    ) )

                    // your own...
                )
                ( )
            )
        ");

    // Visit the parsed S-expr, turn it into a more friendly AST for H-M
    // (see Node, et al, above) and infer some types from the latter
    analyze(source);

    // ...

... sonuç:

id : Function<`u, `u>

o : Function<Function<`z, `aa>, Function<`y, `z>, Function<`y, `aa>>

factorial : Function<Int32, Int32>

fmap : Function<Function<`au, `ax>, List<`au>, List<`ax>>

... Done.

Ayrıca Brian McKenna'nın bitbucket üzerindeki JavaScript uygulamasına da bakın , bu da başlamaya yardımcı olur (benim için çalıştı).

'HTH,

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.