Hindley-Milner คืออะไร?


124

ฉันเจอคำนี้ฮินด์ลีย์ - มิลเนอร์และฉันไม่แน่ใจว่าเข้าใจความหมายหรือไม่

ฉันได้อ่านโพสต์ต่อไปนี้:

แต่ไม่มีรายการเดียวสำหรับคำนี้ในวิกิพีเดียซึ่งมักจะให้คำอธิบายสั้น ๆ แก่ฉัน
หมายเหตุ - ตอนนี้มีการเพิ่มหนึ่งรายการ

มันคืออะไร?
ภาษาและเครื่องมือใดบ้างที่ใช้หรือใช้
คุณช่วยเสนอคำตอบที่กระชับได้ไหม

คำตอบ:


167

Hindley-Milner เป็นระบบประเภทหนึ่งที่ Roger Hindley ค้นพบโดยอิสระ (ผู้ที่มองเรื่องตรรกะ) และต่อมาโดย Robin Milner (ซึ่งกำลังมองหาภาษาโปรแกรม) ข้อดีของ Hindley-Milner คือ

  • รองรับฟังก์ชั่นpolymorphic ; ตัวอย่างเช่นฟังก์ชันที่สามารถให้ความยาวของรายการโดยไม่ขึ้นกับประเภทขององค์ประกอบหรือฟังก์ชันทำการค้นหาแบบไบนารีทรีโดยไม่ขึ้นกับประเภทของคีย์ที่เก็บไว้ในโครงสร้าง

  • บางครั้งฟังก์ชันหรือค่าสามารถมีได้มากกว่าหนึ่งประเภทดังตัวอย่างของฟังก์ชัน length ซึ่งอาจเป็น "list of integers to integer", "list of strings to integer", "list of pair to integer" เป็นต้น บน. ในกรณีนี้เป็นข้อได้เปรียบของสัญญาณของระบบ Hindley-มิลเนอร์คือการที่แต่ละเทอมดีพิมพ์มีที่ไม่ซ้ำกันชนิด "ดีที่สุด"ซึ่งเรียกว่าประเภทหลัก ประเภทหลักของฟังก์ชันความยาวรายการคือ "สำหรับaฟังก์ชันใด ๆจากรายการaถึงจำนวนเต็ม" นี่aคือสิ่งที่เรียกว่า "พารามิเตอร์ชนิด" ซึ่งเป็นที่ชัดเจนในแลมบ์ดาแคลคูลัสแต่นัยในที่สุดการเขียนโปรแกรมภาษาพารา polymorphism (หากคุณเขียนนิยามของฟังก์ชัน length ใน ML คุณจะเห็นพารามิเตอร์ type ดังนี้:

     fun 'a length []      = 0
       | 'a length (x::xs) = 1 + length xs
    
  • หากคำศัพท์มีประเภท Hindley-Milner ประเภทหลักสามารถอนุมานได้โดยไม่ต้องมีการประกาศประเภทหรือคำอธิบายประกอบอื่น ๆ โดยโปรแกรมเมอร์ (นี่เป็นพรแบบผสมผสานอย่างที่ทุกคนสามารถยืนยันได้ว่าใครเคยได้รับการจัดการโค้ด ML จำนวนมากโดยไม่มีคำอธิบายประกอบ)

Hindley-Milner เป็นพื้นฐานสำหรับระบบประเภทของภาษาที่ใช้งานได้เกือบทุกภาษาที่พิมพ์แบบคงที่ ภาษาที่ใช้กันทั่วไป ได้แก่

ภาษาทั้งหมดเหล่านี้ได้ขยาย Hindley-Milner; Haskell, Clean และ Objective Caml ทำในรูปแบบที่ทะเยอทะยานและผิดปกติ (จำเป็นต้องมีส่วนขยายเพื่อจัดการกับตัวแปรที่เปลี่ยนแปลงได้เนื่องจาก Hindley-Milner พื้นฐานสามารถล้มล้างได้โดยใช้ตัวอย่างเช่นเซลล์ที่เปลี่ยนแปลงไม่ได้ซึ่งมีรายการค่าของประเภทที่ไม่ระบุปัญหาดังกล่าวจะถูกจัดการโดยส่วนขยายที่เรียกว่าข้อ จำกัด ของค่า )

ภาษาและเครื่องมือรองอื่น ๆ อีกมากมายที่ใช้ภาษาที่ใช้งานได้พิมพ์ใช้ Hindley-Milner

Hindley-มิลเนอร์เป็นข้อ จำกัด ของระบบ Fซึ่งจะช่วยให้หลายประเภท แต่ที่ต้องมีคำอธิบายประกอบโดยโปรแกรมเมอร์


2
@NormanRamsey ฉันรู้ว่านี่เป็นเรื่องที่ชั่วร้าย แต่ขอบคุณสำหรับการล้างสิ่งที่ทำให้ฉันรำคาญไม่รู้จบ: ทุกครั้งที่ฉันอ้างถึงระบบประเภท hindley-milner จะมีคนตีระฆังในการพูดถึงการอนุมานประเภทจนถึงจุดที่ฉันเริ่มตั้งคำถามว่า HM เป็นประเภทหรือไม่ ระบบหรือแค่อัลกอริธึมการอนุมาน ... ขอบคุณครับผมขอเดาว่าวิกิพีเดียให้ข้อมูลคนที่เข้าใจผิดเกี่ยวกับเรื่องนี้จนถึงขั้นทำให้ผมสับสน ..
Jimmy Hoffa

1
เหตุใดจึงมีความหลากหลายเชิงพาราเมตริกเมื่อเทียบกับความหลากหลายเพียงอย่างเดียว ตัวอย่างที่มี Any you ให้ฉันเห็นว่าเป็นตัวอย่างถ้า polymorphism - ซึ่งสามารถใช้ subtypes แทน supertype ที่ระบุไว้ในคำจำกัดความและไม่ใช่ parametric polymorphism ala C ++ ที่โปรแกรมเมอร์ระบุประเภทที่แท้จริงเพื่อสร้าง ฟังก์ชั่นใหม่
corazza

1
@jcora: ไม่กี่ปีที่ผ่านมา แต่เพื่อประโยชน์ของผู้อ่านในอนาคต: มันเรียกว่าพหุนามพาราเมตริกเนื่องจากคุณสมบัติของพาราเมตริกซึ่งหมายความว่าสำหรับประเภทใด ๆ ที่คุณเสียบอินสแตนซ์ทั้งหมดของฟังก์ชันเช่นlength :: forall a. [a] -> Intจะต้องทำงานเหมือนกันโดยไม่คำนึงถึงa- ทึบแสง; คุณไม่รู้อะไรเกี่ยวกับมัน ไม่มีinstanceof(Java generics) หรือ "การพิมพ์เป็ด" (เทมเพลต C ++) เว้นแต่คุณจะเพิ่มข้อ จำกัด ประเภทพิเศษ (Haskell typeclasses) ด้วยพาราเมตริกคุณจะได้รับข้อพิสูจน์ที่ดีเกี่ยวกับสิ่งที่ฟังก์ชันสามารถทำได้ / ไม่สามารถทำได้อย่างแม่นยำ
Jon Purdy

8

คุณสามารถค้นหาเอกสารต้นฉบับได้โดยใช้ Google Scholar หรือ CiteSeer หรือห้องสมุดมหาวิทยาลัยในพื้นที่ของคุณ อย่างแรกเก่าพอที่คุณอาจต้องหาสำเนาของวารสารที่ผูกมัดฉันหาไม่พบทางออนไลน์ ลิงก์ที่ฉันพบสำหรับอีกอันหนึ่งเสีย แต่อาจมีคนอื่น ๆ คุณจะสามารถค้นหาเอกสารที่อ้างถึงสิ่งเหล่านี้ได้อย่างแน่นอน

Hindley, Roger J, โครงร่างประเภทหลักของวัตถุในตรรกะผสม , ธุรกรรมของสมาคมคณิตศาสตร์อเมริกัน, 1969

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


2
สามารถพบได้ที่นี่: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.67.5276
Magnus


6

การใช้การอนุมานประเภท Hindley-Milner อย่างง่ายใน C #:

การอนุมานประเภท Hindley-Milner เหนือ (Lisp-ish) S- นิพจน์ใน C # 650 บรรทัด

โปรดทราบว่าการนำไปใช้งานอยู่ในช่วงของ C # เพียง 270 บรรทัดหรือมากกว่านั้น (สำหรับอัลกอริทึม W ที่เหมาะสมและโครงสร้างข้อมูลเพียงเล็กน้อยที่จะรองรับ)

ข้อความที่ตัดตอนมาการใช้งาน:

    // ...

    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);

    // ...

... ซึ่งให้ผล:

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.

ดูการใช้งาน JavaScript ของ Brian McKennaบน bitbucket ซึ่งช่วยในการเริ่มต้นด้วย (ใช้ได้ผลกับฉัน)

'HTH,

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.