我编写了一个函数count :: Char -> String -> Int
,用于计算Char
内String
的出现次数。代码示例:
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
。
问题:
答案 0 :(得分:5)
->
是右关联的:
elemIndices :: Eq a => a -> [a] -> [Int]
装置
elemIndices :: Eq a => a -> ([a] -> [Int])
当您在elemIndices
的右侧使用(.) :: (b -> c) -> (a' -> b) -> a' -> c
时,您有
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
删除多余的parens:
count = ((.) . (.)) length elemIndices
前缀表示法:
count = (.) (.) (.) length elemIndices
最大的美容成就。