What is Hindley-Milner?

前端 未结 3 1407
无人及你
无人及你 2020-11-29 15:01

I encountered this term Hindley-Milner, and I\'m not sure if grasp what it means.

I\'ve read the following posts:

  • Steve Yegge - Dynamic Language
3条回答
  •  迷失自我
    2020-11-29 15:13

    Simple Hindley-Milner type inference implementation in C# :

    Hindley-Milner type inference over (Lisp-ish) S-expressions, in under 650 lines of C#

    Note the implementation is in the range of only 270 or so lines of C# (for the algorithm W proper and the few data structures to support it, anyway).

    Usage excerpt:

        // ...
    
        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();
    
        // 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
        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 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);
    
        // ...
    
    
    

    ... which yields:

    id : Function<`u, `u>
    
    o : Function, Function<`y, `z>, Function<`y, `aa>>
    
    factorial : Function
    
    fmap : Function, List<`au>, List<`ax>>
    
    ... Done.
    

    See also Brian McKenna's JavaScript implementation on bitbucket, which also helps to get started (worked for me).

    'HTH,

    提交回复
    热议问题