从旧考试中了解Haskell类型

Kim*_*son 1 haskell

我正在攻读Haskell考试,我对这个问题有点困惑: 在此输入图像描述

我的第一个想法是写这样的东西

paste :: Region -> Image a -> Image a -> Image a
paste (Image bol) img1 img2 = if bol
                              then -- do the pasting
                              else -- well do nothing
Run Code Online (Sandbox Code Playgroud)

但我不知道怎么做粘贴.有人能指出我正确的方向吗?

lef*_*out 8

虽然当你实际参加考试时这很少用,但这里是"教一个人拖网捕鱼"的答案:开始时根本没有定义任何结果,让编译器(必须是GHC≥7.8)评论它.请注意,存根是错误的:如果Image只是一个type-def,则不需要值构造函数Image来对其进行模式匹配.

newtype Image a = Image (Position -> a)
    -- it should be `newtype` instead of `type`, else there
    -- won't be an explicit `Image` value constructor
type Position = (Float, Float)
type Region = Image Bool

paste :: Region -> Image a -> Image a -> Image a
paste (Image bol) img1 img2 = _
Run Code Online (Sandbox Code Playgroud)

GHC将回来

/tmp/wtmpf-file6644.hs:8:31:
    Found hole ‘_’ with type: Image a
    Where: ‘a’ is a rigid type variable bound by
               the type signature for
                 paste :: Region -> Image a -> Image a -> Image a
    ...
Run Code Online (Sandbox Code Playgroud)

好吧,这并不奇怪:我们已经知道结果应该是一个图像.现在,只有一个构造函数Image,即Image我们确定我们需要构建这样的图像.仍然对内部实现一无所知:

paste (Image bol) img1 img2 = Image _
Run Code Online (Sandbox Code Playgroud)

/tmp/wtmpf-file6644.hs:8:37:
    Found hole ‘_’ with type: Position -> a
    Where: ‘a’ is a rigid type variable bound by
               the type signature for
                 paste :: Region -> Image a -> Image a -> Image a
               at /tmp/wtmpf-file6644.hs:7:10
Run Code Online (Sandbox Code Playgroud)

啊啊,所以有一个隐藏在其中的额外功能参数Image!让我们的模式匹配:

paste (Image bol) img1 img2 = Image $ \pos -> _

/tmp/wtmpf-file6644.hs:8:47:
    Found hole ‘_’ with type: a
    ...
Run Code Online (Sandbox Code Playgroud)

好吧,a完全不透明,所以现在我们确定没有进一步的信息我们无能为力.幸运的是,我们确实以参数的形式提供了进一步的信息.正如GHC将通知您:

    ...
    Relevant bindings include
      pos :: Position (bound at /tmp/wtmpf-file6644.hs:8:40)
      img2 :: Image a (bound at /tmp/wtmpf-file6644.hs:8:24)
      img1 :: Image a (bound at /tmp/wtmpf-file6644.hs:8:19)
      bol :: Position -> Bool (bound at /tmp/wtmpf-file6644.hs:8:14)
Run Code Online (Sandbox Code Playgroud)

我们没有太多可以做的事情......这很好,因为这显然该做什么:我们可以pos作为参数提供bol.结果然后键入Bool(与其bol自身不同),因此现在是if交换机的良好候选者.

paste (Image bol) img1 img2 = Image $ \pos -> if bol pos
         then _
         else _
Run Code Online (Sandbox Code Playgroud)

...

Found hole ‘_’ with type: a
      ...
Run Code Online (Sandbox Code Playgroud)

之前看到过,我们需要更多的信息.让我们回顾一下这些论点:Image a仍然可以模式匹配

paste (Image bol) (Image img1) (Image img2)
  = Image $ \pos -> if bol pos
         then _
         else _
Run Code Online (Sandbox Code Playgroud)

现在它说:

    Relevant bindings include
      pos :: Position (bound at /tmp/wtmpf-file6644.hs:9:14)
      img2 :: Position -> a (bound at /tmp/wtmpf-file6644.hs:8:39)
      img1 :: Position -> a (bound at /tmp/wtmpf-file6644.hs:8:26)
      bol :: Position -> Bool (bound at /tmp/wtmpf-file6644.hs:8:14)
Run Code Online (Sandbox Code Playgroud)

啊哈,原来img1img2可能产生的a,因为我们需要的值,我们只需要他们养活Position第一.好吧,我们还有pos,所以很明显该做什么:

paste (Image bol) (Image img1) (Image img2)
  = Image $ \pos -> if bol pos
         then img1 pos
         else img2 pos
Run Code Online (Sandbox Code Playgroud)

...或交换两张图片(自己想一想).但是,实际上没有任何其他定义可以仅使用给定的信息(以及所有信息!)来编写,因此这种类型的孔过程是实现函数的一种非常简单的方法.