【问题标题】:type signature of HaskellHaskell 的类型签名
【发布时间】:2019-10-09 08:24:04
【问题描述】:
cow :: (Eq a) => a -> a -> [a] -> Bool
cow x y z = x && y `elem` z

 foo ::
 foo x y z = x `elem` y && y `elem` z

 bar::
 bar x y = case y of
    Nothing -> x
    Just z  -> x + z

我不知道类型签名应该是什么。

【问题讨论】:

  • 提示:查找elem(+)(&&)的签名。
  • 可能是“elem”用于查找x&&y是否在Z的列表中?我不太确定,所以我使用了 Bool。
  • 你不需要知道一个函数在做什么来确定类型。只需查看您使用的函数的签名,就可以推断出签名。
  • cow 也是错误的。

标签: haskell type-signature


【解决方案1】:

为了确定类型签名。您不需要知道函数在做什么。您可以使用您使用的函数的类型签名,并对其进行推断。

由于您的cow 函数的类型签名并不完全正确,我们将展示如何推导出cow 函数的类型签名,然后将其他两个留作练习。

我们看到cow这里有三个参数:xyz。目前,我们对xyz知之甚少。所以我们将为这些变量分配一个不同的类型变量。所以x :: ay :: bz :: c

接下来我们可以开始推导类型。 cow的函数定义:

cow x y z = x && y `elem` z

可以写成更规范的格式:

cow x y z = (&&) x (elem y z)

因此我们看到我们在这里使用了两个函数:(&&) :: Bool -> Bool -> Boolelem :: (Eq e, Foldable f) => e -> f e -> Bool,我们在这里使用e 而不是f 以避免与我们已经定义的类型变量a 发生“名称冲突” .由于我们使用x 作为(&&) :: Bool -> Bool -> Bool 函数的参数,我们知道x 应该具有Bool 类型,因此a ~ BoolaBool 的类型相同)。此外,我们因此知道(&&) x :: Bool -> Bool

接下来我们看到我们调用了elem :: (Eq e, Foldable f) => e -> f e -> Bool。因此,这意味着y,它是应用于elem 的第一个参数,因此具有e 类型,因此是b ~ e

这进一步意味着elem x因此具有(Eq e, Foldable f) => f e -> Bool类型,我们将此函数应用于z参数。因此这意味着c ~ (Eq e, Foldable f) => f e,并且elem y z 的类型是Bool

由于elem y z的类型是Bool,这与函数(&&) x匹配,因此(&&) x (elem y z)的类型是Bool

因此我们得出:

x :: Bool
y :: e
z :: f e

使用 as 类型约束 Eq eFoldable f。因此,这意味着 cow 具有以下功能:

cow :: (Eq e, Foldable f) => Bool -> e -> f e -> Bool
cow x y z = x && y `elem` z

【讨论】:

  • 当然Foldable f 可以专门化为[],给Bool -> a -> [a] -> Bool
  • @JonPurdy:是的,正确。问题更多在于问题中提议的签名中的x
猜你喜欢
  • 1970-01-01
  • 2015-07-22
  • 2016-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多