组合函数 'length' 和 'elemIndices'
Composing functions 'length' and 'elemIndices'
我编写了一个函数 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
。
问题:
- 为什么我写的作文编译不通过?
- 我的推理哪里出错了?
->
在类型中是右结合的:
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
减少埃塔:
count x = length . elemIndices x
你可能应该到此为止,因为这是事情变得有点疯狂的地方。
前缀表示法:
count x = (.) length (elemIndices x)
(.)
的定义:
count x = ((.) length . elemIndices) x
减少埃塔:
count = (.) length . elemIndices
或使用运算符部分:
count = (length .) . elemIndices
等等,还有更多!
前缀表示法:
count = (.) ((.) length) elemIndices
(.)
的定义:
count = (((.) . (.)) length) elemIndices
删除多余的括号:
count = ((.) . (.)) length elemIndices
前缀表示法:
count = (.) (.) (.) length elemIndices
美到极致。
我编写了一个函数 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
。
问题:
- 为什么我写的作文编译不通过?
- 我的推理哪里出错了?
->
在类型中是右结合的:
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
减少埃塔:
count x = length . elemIndices x
你可能应该到此为止,因为这是事情变得有点疯狂的地方。
前缀表示法:
count x = (.) length (elemIndices x)
(.)
的定义:
count x = ((.) length . elemIndices) x
减少埃塔:
count = (.) length . elemIndices
或使用运算符部分:
count = (length .) . elemIndices
等等,还有更多!
前缀表示法:
count = (.) ((.) length) elemIndices
(.)
的定义:
count = (((.) . (.)) length) elemIndices
删除多余的括号:
count = ((.) . (.)) length elemIndices
前缀表示法:
count = (.) (.) (.) length elemIndices
美到极致。