【问题标题】:Syntax for List Patterns in Function Declaration函数声明中列表模式的语法
【发布时间】:2017-03-27 20:42:09
【问题描述】:

我正在学习 Haskell,并且一直在编写各种相当琐碎的函数来掌握该语言。我写了这个函数:

doubleOneOrTail :: [t]->[t]
doubleOneOrTail [x] = [x,x]
doubleOneOrTail (x:xs)  = xs

这正是所说的。将 1 个元素的列表加倍,或返回多个元素列表的尾部。这种通用语法适用于单个元素列表或列表列表等。我可以将此函数重写为以下内容:

doubleOneOrTail :: [[t]]->[[t]]
doubleOneOrTail [[x]] = [[x,x]]
doubleOneOrTail (x:xs)  = xs

如果我输入以下内容,这将引发错误:

doubleOneOrTail [1,2,3]

但它确实接受这一点:

doubleOneOrTail [[[[1,2,3],[2]]]]

将其视为具有单个元素的列表(该元素是列表的列表)并将其加倍。

显然,模式 [a]->[a] 不匹配单个元素的列表,但在某种程度上匹配任何列表顺序。 Whlie [[a]]->[[a]] 也匹配多个列表顺序(尽管不是仅包含单个元素的列表)。如果有人能解释这是如何工作的,将不胜感激。

第二个问题是有可能(甚至是可取的)有一个函数声明,它专门采用列表的特定顺序。只说列表?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    听起来您对这里的令人惊讶的事情有很好的理解:[a] 是任何类型事物的列表,包括列表列表。您可以手动计算类型推断器自动执行的操作。假设,使用你的第一个定义,我们写:

    let xs = [[[1,2], [3,4]], [[5]]]
    in doubleOneOrTail xs
    

    此时,GHC 必须确保类型与我们匹配。

    xs :: [[[Integer]]] -- really could be any Num type, but assume Integer
    

    现在,由于我们使用[[[Integer]]] 作为参数调用doubleOneOrTail,GHC 必须统一类型[a][[[Integer]]],这意味着找到一些具体的类型来代替@ 987654328@ 使这两种类型匹配。只有一个正确答案:

    [a] ~ [[[Integer]]]
    a ~ [[Integer]]
    

    因此,我们将事物列表加倍或拖尾,其中每个事物都是数字列表。并且由于类型确实统一,GHC 给出了所有明确的,函数调用编译,结果我们得到[[[5]]]

    关于您的第二个问题,您是否可以或应该限制列表的特定深度:通常您不应该。这种函数称为parametrically polymorphic,这意味着它适用于任何类型的a,无论它是什么;这是一个有用的属性,最好尽可能保留。如果您的函数不需要查看其a 类型的值即可正确执行,则它应该允许它们为任何类型。

    假设您仍想限制其类型?我不知道如何将其限制为深度一列表而不添加其他一些附带限制。例如,您可以说它必须是一个数字列表(并希望没有人为列表定义 Num 实例!):

    doubleOneOrTail :: Num a => [a] -> [a]
    

    或者您可以将其限制为非常特定的类型,例如[Int]。这将保证它只能用该类型调用。

    doubleOneOrTail :: [Int] -> [Int]
    

    但如上所述,所有这些方法都不必要地限制了函数的类型。最好尽可能一般地定义它,并找到其他方法来满足您想要限制其类型的任何其他问题。

    【讨论】:

    • 感谢您的帮助。因此,当我执行 [[a]]->[[a]] 时,它只是删除了两个级别的索引来确定当我传入 [[[[a]]]] 时 a 应该是什么类型。 (这可能会导致奇怪和不直观的结果)
    【解决方案2】:

    @amalloy 答案的一点补充。很可能你会很好地使用 Enum 类约束:

    doupbleOneOrTrail :: (Enum t) => [t] -> [t]
    

    所以您的函数接受字符、数字、布尔值等列表

    λ: doubleOneOrTail "foo"
    "oo"
    λ: doubleOneOrTail [False]
    [False,False]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-07
      • 1970-01-01
      • 1970-01-01
      • 2010-12-07
      • 2014-07-12
      相关资源
      最近更新 更多