【问题标题】:Explicit type signatures for polymorphic types. Part II多态类型的显式类型签名。第二部分
【发布时间】:2010-10-23 20:53:40
【问题描述】:

这是对previous question; I got an answer I didn't really understand 的跟进,但已被接受。所以我再问一遍。

我还是不明白这是怎么回事:

type Parse a b = [a] -> [(b,[a])]
build :: Parse a b -> ( b -> c ) -> Parse a c
build p f inp = [ (f x, rem) | (x, rem) <- p inp ]

现在,显然p 绑定到Parse a b 类型的第一个参数。而且,很明显f 绑定到第二个参数(b -&gt; c)。我的问题仍然是inp 绑定到什么?

如果Parse a b[a] -&gt; [(b,[a])] 的类型同义词,我认为从最后一个问题中我可以替换它:

build :: [a] -> [(b,[a])] -> ( b -> c ) -> [a] -> [(c,[a])]

但是,我认为这个定义也没有任何意义:

build p f inp = [ (f x, rem) | (x, rem) <- p inp ]

有人能解释一下类型同义词吗?

【问题讨论】:

    标签: haskell types polymorphism type-synonyms


    【解决方案1】:

    现在,很明显,p 绑定到 Parse a b 类型的第一个参数。而且,显然 f 绑定到第二个参数 (b -> c)。我的问题仍然是 inp 绑定到什么?

    [a] 类型的参数

    如果 Parse a b 是 [a] -> [(b,[a])] 的类型同义词,我认为从最后一个问题中我可以替换它:

    build :: [a] -> [(b,[a])] -> ( b -> c ) -> [a] -> [(c,[a])]
    

    几乎;你需要用括号括起来:

    build :: ([a] -> [(b,[a])]) -> ( b -> c ) -> ([a] -> [(c,[a])])
    

    因为-&gt; 是右结合的,所以你可以去掉末尾的括号,但不能去掉开头的括号,所以你得到:

    build :: ([a] -> [(b,[a])]) -> ( b -> c ) -> [a] -> [(c,[a])]
    

    这应该很明显为什么inp 的类型为[a]

    【讨论】:

      【解决方案2】:

      您可以替换——但不要忘记括号!那应该是:

      build :: ( [a] -> [(b,[a])] ) -> ( b -> c ) -> ( [a] -> [(c,[a])] )
      

      因为函数箭头是右关联的,所以您可以转储右侧的一组括号,但至关重要的是,您不能丢弃左侧的新括号:

      build :: ( [a] -> [(b,[a])] ) -> ( b -> c ) -> [a] -> [(c,[a])]
      

      所以现在当你有build p f inp 行时,你可以看到:

      p :: ( [a] -> [(b,[a])] )
      f :: ( b -> c )
      inp :: [a]
      

      那么我们可以看到:

      p inp :: [(b, [a])]
      

      因此:

      x :: b
      rem :: [a]
      

      还有:

      f x :: c
      (f x, rem) :: (c, [a])
      

      因此整个列表理解的类型为[(c, [a])]——它与build 应该返回的完全匹配。希望对您有所帮助!

      【讨论】:

        【解决方案3】:

        如果你替换

        type Parse a b = [a] -> [(b,[a])]
        

        进入

        build :: Parse a b -> ( b -> c ) -> Parse a c
        

        你得到

        build :: ([a] -> [(b,[a])]) -> (b -> c) -> [a] -> [(c,[a])]
        

        请记住,x -&gt; y -&gt; zx -&gt; (y -&gt; z) 的简写,它与 (x -&gt; y) -&gt; z 非常不同。第一个是一个函数,它接受两个参数xy 并返回z [准确地说,它接受一个参数x 并返回一个函数,它接受y 并返回z];第二个是接受一个函数 x -&gt; y 并返回z

        【讨论】:

          【解决方案4】:

          这里要记住的重要一点是,类型签名中的箭头-&gt; 是右关联的。 a -&gt; (b -&gt; c) 类型与 a -&gt; b -&gt; c 类型相同。

          所以类型

          Parse a b -> ( b -> c ) -> Parse a c
          

          解决

          ([a] -> [(b,[a])]) -> ( b -> c ) -> ([a] -> [(c,[a])])
          

          通过关联性,您可以删除最后一个括号,但不能删除第一个括号。这给了你

          ([a] -> [(b,[a])]) -> ( b -> c ) -> [a] -> [(c,[a])]
          

          它允许您使用 3 个参数为 build 编写公式。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-15
            • 2018-11-11
            • 2015-04-18
            • 1970-01-01
            • 2019-02-21
            • 1970-01-01
            相关资源
            最近更新 更多