haskell - 使函数与 'if' 无点

标签 haskell functional-programming pointfree

我在 Haskell 中有一个任务(不,这不是我的作业,我正在为考试而学习)。

任务是:

Write point-free function numocc which counts occurrences of element in given lists. For example: numocc 1 [[1, 2], [2, 3, 2, 1, 1], [3]] = [1, 2, 0]



这是我的代码:
addif :: Eq a => a -> Int -> a -> Int
addif x acc y = if x == y then acc+1 else acc

count :: Eq a => a -> [a] -> Int
count = flip foldl 0 . addif

numocc :: Eq a => a -> [[a]] -> [Int]
numocc = map . count
numocccount是“无点”,但他们正在使用函数 addif不是。

我不知道如何执行 addif 功能免积分。有什么办法吗if声明点免费?也许有一个使用 no if 的技巧?

最佳答案

我会使用您可以轻松转换 Bool 的事实。到 Int使用 fromEnum :

addif x acc y = acc + fromEnum (x == y)

现在您可以开始应用通常的技巧来使其无点
-- Go prefix and use $
addif x acc y = (+) acc $ fromEnum $ (==) x y
-- Swap $ for . when dropping the last argument
addif x acc = (+) acc . fromEnum . (==) x

等等。我不会带走让它变得免费的所有乐趣,尤其是当有工具可以为你做这件事的时候。

或者,您可以编写一个函数,例如
count x = sum . map (fromEnum . (==) x)

这几乎是免费的,并且有一些技巧可以让你更接近,尽管它们很快就会变得非常讨厌:
count = fmap fmap fmap sum map . fmap fmap fmap fromEnum (==)

在这里,我认为使用 fmap 实际上看起来更好。而不是 (.) ,尽管您可以替换每个 fmap(.)这将是完全相同的代码。本质上,(fmap fmap fmap)将单个参数和两个参数函数组合在一起,如果您将其命名为 .:你可以这样写
count = (sum .: map) . (fromEnum .: (==))

分解:
> :t fmap fmap fmap sum map
Num a => (a -> b) -> [a] -> b

所以它从 b 获取一个函数到数字 ab 的列表s,并返回 a ,还不错。
> :t fmap fmap fmap fromEnum (==)
Eq a => a -> a -> Int

而这个类型可以写成Eq a => a -> (a -> Int) ,这是需要注意的重要一点。这使得该函数的返回类型与 fmap fmap fmap sum map 的输入相匹配。与 b ~ Int , 所以我们可以将它们组合成 Eq a => a -> [a] -> Int 类型的函数.

关于haskell - 使函数与 'if' 无点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34342516/

相关文章:

haskell 无法将预期类型 `Maybe Text' 与实际类型 `Text' 匹配

haskell - 是否有可能有一个 "local"类型类实例?

javascript - 如何使用 Ramda 按值进行无点数组搜索

javascript - Javascript 中的短路 Array.reduce

haskell - Haskell 中参数在函数组合中的应用

Haskell map /zip 与。列表理解

Haskell:在不使用 spawn 的情况下拆分管道(广播)

node.js - 从 Node.JS 调用 Haskell

haskell - 如何捕获并忽略 Haskell 中的错误调用

scala - 如何交换到 Seq 中的元素