【问题标题】:Composing functions 'length' and 'elemIndices'组合函数 'length' 和 'elemIndices'
【发布时间】:2017-05-01 11:02:59
【问题描述】:

我编写了一个函数count :: Char -> String -> Int,它计算CharString 中出现的次数。代码示例:

module Main where

import Data.List

main :: IO ()
main = do
        print $ count 'a' "abcaaba"

count :: Char -> String -> Int
count = length . elemIndices

我得到的编译错误是

* Couldn't match type `Int' with `String -> Int'
  Expected type: Char -> String -> Int
    Actual type: Char -> Int
* Possible cause: `(.)' is applied to too many arguments
  In the expression: length . elemIndices
  In an equation for `count': count = length . elemIndices

好的,我可以写count x y = length $ elemIndices x y,这很有效。但我认为我们有

(1)(.) :: (b -> c) -> (a -> b) -> a -> c

(2)elemIndices :: Eq a => a -> [a] -> [Int]

(3)length :: [a] -> Int

如果count 是 (2) 和 (3) 的组合,那么在 (1) 中我们显然需要 a = Char -> [Char]c = Int。如果b = [Int] 我们得到

(1') (.) :: ([Int] -> Int) -> (Char -> [Char] -> [Int]) -> Char -> [Char] -> Int

这意味着我可以编写 (2) 和 (3) 来获得 Char -> [Char] -> Int

问题:

  1. 为什么我写的作文编译失败?
  2. 我的推理哪里出了问题?

【问题讨论】:

  • 在许多 Haskell 书籍和教程中,字里行间提到的一些 Haskell 基础知识有时会被跳过或忽略。 This 文章值得一看。

标签: haskell function-composition


【解决方案1】:

-> in types 是右结合的:

elemIndices :: Eq a => a -> [a] -> [Int]

意思

elemIndices :: Eq a => a -> ([a] -> [Int])

当您在(.) :: (b -> c) -> (a' -> b) -> a' -> c 的右侧使用elemIndices 时,您有

  • a' = a
  • b = [a] -> [Int]

这就是问题所在,因为length 没有将[a] -> [Int](一个函数)作为输入;它想要一个列表。


你可以做的是:

count x y = length (elemIndices x y)

这与(根据(.)的定义)相同:

count x y = (length . elemIndices x) y

Eta 减少:

count x = length . elemIndices x

你应该在这里停下来,因为这会让事情变得有点疯狂。


前缀表示法:

count x = (.) length (elemIndices x)

(.)的定义:

count x = ((.) length . elemIndices) x

Eta 减少:

count = (.) length . elemIndices

或者使用操作符部分:

count = (length .) . elemIndices

但等等,还有更多!

前缀表示法:

count = (.) ((.) length) elemIndices

(.)的定义:

count = (((.) . (.)) length) elemIndices

删除多余的括号:

count = ((.) . (.)) length elemIndices

前缀表示法:

count = (.) (.) (.) length elemIndices

达到最大的美丽。

【讨论】:

  • 感谢您的非凡回答。它不仅全面且内容丰富,而且很有趣! :-)
猜你喜欢
  • 2018-10-09
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 1970-01-01
  • 2013-10-07
相关资源
最近更新 更多