【问题标题】:How does haskell break a list in a pattern for head functionhaskell如何打破头部功能模式中的列表
【发布时间】:2021-02-06 23:25:21
【问题描述】:

在学习 haskell 时,我无法理解 haskell 是如何自动匹配提取列表头部的模式的。

head' :: [a] -> a  
head' [] = error "Can't find head in an Empty list!" 
-- How does haskell break the list into x(first) and xs(rest)? 
head' (x:xs) = x

我读过[1,2,3]1:2:3:[] 的语法糖。 那么: 是一个接受任何参数并添加到右手参数的函数? 列表如何向后分解为两个变量 head 和 rest? [1,2,3] --> (x:xs)??

colon_operator :: a -> [a]
-- not sure how the function would look

对不起,如果我不能简明扼要地解释我的问题,我在 haskell 方面不是很擅长。

【问题讨论】:

  • 您是否熟悉代数数据类型?如果是这样,快速的答案是: 不是普通函数而是列表构造函数;列表实际上定义为data [a] = (:) a [a] | []
  • 您的问题是关于编译器方面的如何 实现逻辑吗?或者关于语言是如何定义的?目前还不清楚是什么让您感到困惑……或者您是在看一般模式匹配的介绍吗?
  • @SukhinderpalMann 这是代数数据类型的定义。您可以在任何 Haskell 教程中了解有关它们的更多信息,例如learnyouahaskell.com/making-our-own-types-and-typeclasses。 (我应该注意,虽然我的定义在语法上不是有效的 Haskell,但仅作为示例:更好的版本是 data List a = Cons a (List a) | Nil。)
  • [1,2,3]1:2:3:[] 的语法糖,实际上1:(2:(3:[])),即(x:xs),其中x = 1xs = (2:(3:[]))。所以这里没有“落后”“爆炸”,也不存在解构。每个: 都有两个 字段。就是这样。
  • 让我为你找到一个链接......例如here's 我的回答带有链接和一些措辞。

标签: haskell pattern-matching


【解决方案1】:

警告讲师:这是第零个近似值,在很多方面都是错误的,但至少它是第零个近似值!

使用伪代码,当您调用[]: 时,会创建一个新的数据结构。下面是你可以用命令式语言编写结构的方法:

structure {
    int constructor
    ptr head
    ptr tail
} list

当您编写empty = [] 时,它会分配一个新的list,并以这种方式填充它:

empty = alloc(list)
empty.constructor = 0 // 0 means we used [] to construct this

headtail 指针未初始化,因为它们未被使用。当您编写not_empty = 3 : [4] 时,它会分配一个新的list,并以这种方式填充它:

// three is a pointer to 3
// four is a pointer to [4]
not_empty = alloc(list)
not_empty.constructor = 1 // 1 means we used : to construct this
not_empty.head = three
not_empty.tail = four

现在,当您对列表进行模式匹配时,这对应于检查constructor 字段。所以如果你写,说:

case not_empty of
    [] -> 7
    x:xs -> 20 + x

那么必然发生的事情是这样的:

if not_empty.constructor == 0
    return 7
elseif not_empty.constructor == 1
    return 20 + dereference(not_empty.head)
endif

(同样,如果您提到了xs,它会取消引用tail 指针。)

在构造list 结构和对其进行模式匹配之间,您现在了解了用于在列表上构建every 函数的基本构建块!在最基本的层面上,这是您唯一可以做的两件事list-y。

【讨论】:

  • 谢谢!我希望有更多这样的示例来比较函数式代码和用 C/C++ 编写的传统命令式代码。如果您知道一些文档,我可以在其中看到 C/C++ 中的比较/类似实现或基本 Haskell 函数/行为的内部工作原理,那将是非常棒的!这对我有帮助,haskell 的类型推断和模式匹配让我大吃一惊,我在 1 周前才开始使用 haskell。
  • @SukhinderpalMann Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine 是对 Haskell 编译的极好介绍。它非常平易近人,并讨论了旧版本 GHC 背后的实际技术。 (他们实际上讨论了两种实现方法,并且他们已经从那里详细讨论的一种切换到他们忽略的一种。)
  • 可以针对任何其他流行语言进行比较,这不是问题。我可能犯了罪,但我看到了一些用 JS 编写的疯狂 FP(不是真正的 FP)库/框架,如 Elm、faylang 等。它们很诱人,只是为了让我有一些东西可以并排比较以了解haskell/FP 代码更好。
【解决方案2】:

[1,2,3]1:[2,3] 的语法糖,即...

...(x:xs) 其中x = 1xs = [2,3]

所以这里没有“落后”“爆炸”,不,解构

每个: 都有两个 字段。就是这样。

【讨论】:

    猜你喜欢
    • 2022-12-01
    • 1970-01-01
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    相关资源
    最近更新 更多