haskell函数类型简化了f ::b-> a-> a-> c->b-> a-> b-> c

问题描述

请仅寻找此功能类型的说明

f x y z = x y (y z)

序曲说的是

f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c

但是我无法通过任何已知方法获得结果¬

最诚挚的问候。

解决方法

U,那些“手动键入此表达式的类型”练习非常愚蠢。我不知道为什么讲师会继续把他们安排在作业中。

实际上,实际上更相关的是走另一条路:给定类型,找到实现。因此,让我从这个角度回答这个问题:您已经知道

f :: ((b -> a) -> a -> c) -> (b -> a) -> b -> c
--   └──────────────────┘    └──────┘   └─┘

...因此您有三个参数可以接受,足够合理,可以将它们称为xyz

f x y z = _

您最终要寻找c,而您唯一可用的c就是x的最终结果

    x :: (b -> a) -> a -> c
    --   └──────┘   └─┘

...这需要两个参数

f x y z = x _ _

...类型为b -> aa的...。让我们检查一下可用的东西

    y :: b -> a
    z :: b

太好了,我们可以直接使用y作为第一个参数

f x y z = x y _

对于第二个参数,我们需要一个a。好吧,zb,不起作用,但是当给定ya会产生b,因此我们可以传递{{1 }},最终以

y z

或者我们更喜欢用Haskell f x y z = x y (y z) 来写。

现在换一种方式:让我们从η简化形式开始

f x y = x y . y

这是一条管道,因此让我们开始为传递参数指定名称f x y = x y . y

p

该参数首先传递给 x y . y :: p -> _ ,所以我们有

y
紧随其后的

,因为 y :: p -> _ 也是y的第一个参数

x

此外, x :: (p -> _) -> _ 然后接受(在管道中)从x出来的任何内容

y

让我们将最终结果称为 y :: p -> r x :: (p -> r) -> r -> _

q

并按照给定的方式编写整个功能:

        y :: p -> r
        x :: (p -> r) -> r -> q

重命名类型变量后,这与开始时的含义相同。

,

f x y z = x y (y z)中,您可以进行以下推理:

  • 我们不对任何事物应用z,因此它可以具有任意类型;称为u1(代表未知的数字)。

  • y应用于z,因此其参数类型为u1,但是返回类型为另一个未知类型u2。因此y :: u1 -> u2

  • y z的类型为u2

  • x应用于y y z,因此必须具有类似(u1 -> u2) -> u2 -> u3的类型;没有理由假设任何一个参数具有相同的类型,或者任何一个类型都与返回类型相同。

  • f的返回值与x的返回值相同,即u3

将其放到一起

f :: ((u1 -> u2) -> u2 -> u3) -> (u1 -> u2) -> u1          ->    u3
     ------------------------    ----------    --                --
         type of x                type of y    type of z        end result of f

由于各个类型变量的名称除了将不同类型分开之外并不重要,因此我们可以使用

对其进行重命名
  • u1 ~ b
  • u2 ~ a
  • u3 ~ c

获取您查找的类型

f :: ((b  -> a) -> a  -> c) -> (b  -> a) -> b  -> c