gpt4 book ai didi

haskell - 这个函数可以写成无点风格吗?如果不是,为什么?

转载 作者:行者123 更新时间:2023-12-02 01:33:40 24 4
gpt4 key购买 nike

一个相关问题是 this ,但有些答案说几乎任何东西都可以免费,那么这个功能有什么问题呢?

\[x] -> x
http://pointfree.io/似乎无法以无点风格编写它。这是否意味着它不能这样写?如果是这样,它的理论原因是什么?
我只能观察到上面的函数是 head 的“残缺”版本(或 last ,fwiw)只能在单例列表上操作。实际上,应用于非单例列表时,它会在 ghci 中出现这种错误。 :
*** Exception: <interactive>:380:5-13: Non-exhaustive patterns in lambda
也许模式上的“非穷举性”是某些函数不能用无点样式编写的原因?
根据答案进行编辑:
我没想到我的问题的答案会如此复杂(我觉得我只是认为简短的答案是否定的,实际上它不能),所以我需要抽出时间仔细阅读它们,尝试一下,然后把我的思想围绕着他们,否则我无法决定应该接受哪一个。目前,对 Jon Purdy 的回答 +1,我可以很容易地理解这是我将在普通代码中停止的地方。

最佳答案

好吧,数据类型不是函数。只要您的函数没有解开任何数据值(即它只是在函数/构造函数之间打乱它们),您就可以无点编写它,但根本没有无点匹配的语法。但是,每种数据类型只需要一个非无点函数:折叠。在 Haskell 中,数据类型几乎是由它们的折叠定义的。以相关数据类型的折叠为原语,您可以自由地重写任何功能点。请注意,实际上有几种可能的“折叠”。对于 [a] ,递归的(来自 Church/Böhm-Berarducci 编码)是 foldr :: (a -> b -> b) -> b -> [a] -> b .另一种可能的折叠是“case -but-it's-a-function”一个,(a -> [a] -> b) -> b -> [a] -> b ,它来自 Scott 编码(然后可以使用 fix 恢复递归,这是另一个“pointful pointfree primitive”),但是,正如@SilvioMayolo 所指出的,标准库中没有这样的函数。两者都可以,但我们没有预定义后者,所以让我们使用 foldr .

\[x] -> x
可以写
fst . foldr (\x f -> (snd f x, \_ -> error "got (_ : _ : _) wanted [x]")) (error "got [] wanted [x]", id)
-- I don't care enough to replicate the exact exceptions.
-- this is "flattened" from
let fold [] = (error "got [] wanted [x]", id)
fold (x : xs) = (snd (fold xs) x, \_ -> error "got (_ : _ : _) wanted [x]")
in fst . fold
fold返回一对,基本上是 (what to return if this was the entire list, how to transform the head if it wasn't) .对于 [] ,如果这是整个列表,我们希望返回一个错误,否则在我们点击 [] 之前通过该元素.对于 x : xs ,如果它前面有一个元素,我们想忽略它并返回一个错误,如果没有,我们想将它传递给 snd (fold xs) , 检查是否 xs = []否则会出错。我们已经消除了所有匹配项,因此只需通过 pointfree.io 推送即可获得 \x f -> _foldr 的参数中出去:
behead = fst . foldr (flip flip (const (error "got (_ : _ : _) wanted [x]")) . ((,) .) . flip snd) (error "got [] wanted [x]", id)
ghci> :t behead
behead :: Foldable t => t c -> c
ghci> behead []
*** Exception: got [] wanted [x]
ghci> behead [1]
1
ghci> behead [1, 2]
*** Exception: got (_ : _ : _) wanted [x]
ghci> behead [1..]
*** Exception: got (_ : _ : _) wanted [x]
迷人的。
注意:此答案的先前版本使用“内联”辅助数据类型,主要是因为它只是在我编写它时“来到我身边”。但是,它无法正确处理无限列表( behead [1..] 会挂起)。这个版本使用内置的对作为辅助数据类型,它有足够的库支持,我不必内联它们以使其无点。内联 (,) 稍微困难一些,从而消除 fst 的实现内部的点满性和 snd ,但仍然可以使用这种新类型:
newtype Pair a b = Pair { unPair :: forall r. (a -> b -> r) -> r }
或者,在类型上作弊并使用它:
-- residual pointfullness can be reduced by pointfree.io
\xs -> foldr (\x r f -> f (r (const id) x) (\_ -> error "got (_ : _ : _) wanted [x]")) (\f -> f (error "got [] wanted [x]") id) xs (\x _ _ -> x) undefined

关于haskell - 这个函数可以写成无点风格吗?如果不是,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62803061/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com