什么是欣德利米尔纳?

发布于 2024-07-10 04:25:43 字数 785 浏览 7 评论 0原文

我遇到了这个术语Hindley-Milner,我不确定是否理解它的含义。

我读过以下帖子:

但是维基百科中没有这个术语的单个条目,通常为我提供简洁的解释。
注意 - 已现已添加

这是什么?
什么语言和工具实现或使用它?
请您提供一个简洁的答案好吗?

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

I've read the following posts:

But there is no single entry for this term in wikipedia where usually offers me a concise explanation.
Note - one has now been added

What is it?
What languages and tools implement or use it?
Would you please offer a concise answer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

染年凉城似染瑾 2024-07-17 04:25:43

Hindley-Milner 是由 Roger Hindley(研究逻辑)和后来的 Robin Milner(研究编程语言)独立发现的类型系统。 Hindley-Milner的优点是

  • 支持多态函数; 例如,一个函数可以为您提供与元素类型无关的列表长度,或者一个函数可以独立于树中存储的键的类型进行二叉树查找。

  • 有时一个函数或值可以有多种类型,如长度函数的示例:它可以是“整数到整数的列表”、“字符串到整数的列表”, “整数对列表”,等等。 在这种情况下,Hindley-Milner 系统的一个显着优势是每个类型正确的术语都有一个独特的“最佳”类型,称为主要类型。 列表长度函数的主要类型是“对于任何a,从a列表到整数的函数”。 这里的 a 是所谓的“类型参数”,它在 lambda 演算中是显式的,但在大多数编程语言中是隐式的。 类型参数的使用解释了为什么 Hindley-Milner 是一个实现参数化多态性的系统。 (如果你用 ML 编写长度函数的定义,你可以这样看到类型参数:

     fun '长度[] = 0 
         |   '长度 (x::xs) = 1 + 长度 xs 
      
  • 如果一个术语具有 Hindley-Milner 类型,则主要类型可以是无需程序员进行任何类型声明或其他注释即可推断(这是一个好坏参半的事情,因为任何人都可以证明谁曾在没有注释的情况下处理过大量机器学习代码。)

Hindley-Milner 是几乎所有静态类型函数语言的类型系统的基础,常用的此类语言包括

所有这些语言都扩展了 Hindley-Milner; Haskell、Clean 和 Objective Caml 以雄心勃勃且不寻常的方式做到了这一点。 (需要扩展来处理可变变量,因为基本的 Hindley-Milner 可以使用例如保存未指定类型的值列表的可变单元格来破坏。此类问题可以通过名为 值限制。)

许多其他小语言和工具基于类型化函数语言使用 Hindley-Milner。

Hindley-Milner 是 System F 的限制,它允许更多类型,但需要注释由程序员

Hindley-Milner is a type system discovered independently by Roger Hindley (who was looking at logic) and later by Robin Milner (who was looking at programming languages). The advantages of Hindley-Milner are

  • It supports polymorphic functions; for example, a function that can give you the length of the list independent of the type of the elements, or a function does a binary-tree lookup independent of the type of keys stored in the tree.

  • Sometimes a function or value can have more than one type, as in the example of the length function: it can be "list of integers to integer", "list of strings to integer", "list of pairs to integer", and so on. In this case, a signal advantage of the Hindley-Milner system is that each well-typed term has a unique "best" type, which is called the principal type. The principal type of the list-length function is "for any a, function from list of a to integer". Here a is a so-called "type parameter," which is explicit in lambda calculus but implicit in most programming languages. The use of type parameters explains why Hindley-Milner is a system that implements parametric polymorphism. (If you write a definition of the length function in ML, you can see the type parameter thus:

     fun 'a length []      = 0
       | 'a length (x::xs) = 1 + length xs
    
  • If a term has a Hindley-Milner type, then the principal type can be inferred without requiring any type declarations or other annotations by the programmer. (This is a mixed blessing, as anyone can attest who has ever been handled a large chunk of ML code with no annotations.)

Hindley-Milner is the basis for the type system of almost every statically typed functional language. Such languages in common use include

All these languages have extended Hindley-Milner; Haskell, Clean, and Objective Caml do so in ambitious and unusual ways. (Extensions are required to deal with mutable variables, since basic Hindley-Milner can be subverted using, for example, a mutable cell holding a list of values of unspecified type. Such problems are dealt with by an extension called the value restriction.)

Many other minor languages and tools based on typed functional languages use Hindley-Milner.

Hindley-Milner is a restriction of System F, which allows more types but which requires annotations by the programmer.

悲凉≈ 2024-07-17 04:25:43

您也许可以使用 Google Scholar 或 CiteSeer 或您当地的大学图书馆找到原始论文。 第一个已经足够旧了,你可能必须找到该期刊的装订本,我在网上找不到。 我找到的另一个链接已损坏,但可能还有其他链接。 您肯定能够找到引用这些内容的论文。

Hindley,Roger J,组合逻辑中对象的主要类型方案
美国数学会汇刊,1969 年。Milner

, Robin,类型多态性理论,计算机与系统科学杂志,1978 年。

You may be able to find the original papers using Google Scholar or CiteSeer -- or your local university library. The first is old enough that you may have to find bound copies of the journal, I couldn't find it online. The link that I found for the other one was broken, but there might be others. You'll certainly be able to find papers that cite these.

Hindley, Roger J, The principal type scheme of an object in combinatory logic,
Transactions of the American Mathematical Society, 1969.

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

撩起发的微风 2024-07-17 04:25:43

C# 中的简单 Hindley-Milner 类型推断实现:

Hindley-Milner 对(Lisp-ish)S 表达式的类型推断,在下面650 行 C#

请注意,实现仅包含 270 行左右的 C# 代码(无论如何,对于算法 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.

另请参阅 bitbucket 上的 Brian McKenna 的 JavaScript 实现 ,这也有助于入门(对我有用)。

'哈,

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

    // ...

... which yields:

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.

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

'HTH,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文