我不确定如何实施.
和$
运算符来简化以下定义:
compress :: [Char] -> [Char]
compress [] = []
compress as
| g as 1 == 1 = [head as] ++ compress (drop 1 as)
| otherwise = [head as] ++ show (g as 1) ++ compress (drop (g as 1) as)
g :: [Char] -> Int -> Int
g [] i = i
g (a:[]) i = i
g (a:as) i
| a == head as = g as (i + 1)
| otherwise = i
main = getLine >>= \str -> putStrLn $ compress str
我已经读过.
运算符是一个功能组合,因此一个函数的输出转到另一个函数的输入,而$
是括号的替代。
因此,我尝试将其更改为
compress :: [Char] -> [Char]
compress [] = []
compress as
| g as 1 == 1 = [head as] ++ compress . drop 1 as
| otherwise = [head as] ++ show (g as 1) ++ compress . drop (g as 1) as
g :: [Char] -> Int -> Int
g [] i = i
g (a:[]) i = i
g (a:as) i
| a == head as = g as (i + 1)
| otherwise = i
main = getLine >>= \str -> putStrLn $ compress str
但我收到类型错误
could not match '[Char]' with a0 -> [Char]
我对如何使用这些运营商感到有点困惑。
答案 0 :(得分:3)
我在这段代码中看不到使用($)
和(.)
的方法。
但是,您可以简化代码:
compress :: [Char] -> [Char]
compress [] = []
compress as@(x:xs)
| g as 1 == 1 = x : compress xs
| otherwise = x : show (g as 1) ++ compress (drop (g as 1) as)
g :: [Char] -> Int -> Int
g (a:as) i
| a == head as = g as (i + 1)
| otherwise = i
g _ i = i
main = getLine >>= putStrLn . compress
例如,这个:
[head as] ++ compress (drop 1 as)
与此相同:
head as : compress (drop 1 as)
通过使用模式匹配,它变得更短:
x : compress xs
您要使用的运算符通常用于编写函数的较短版本(括号较少)。例如,您的compress
函数可以这样写:
compress :: [Char] -> [Char]
compress = concatMap (\x -> head x : show (length x)) . group
而不是:
compress :: [Char] -> [Char]
compress xs = concat $ map (\x -> head x : show (length x)) $ group xs
甚至是
compress :: [Char] -> [Char]
compress xs = concatMap (\x -> head x : show (length x)) (group xs)
这是一个更简单的例子:
capitalizeWords :: String -> String
capitalizeWords string = unwords (map (\(f:rest) -> toUpper f : rest) (words string))
main = putStrLn (capitalizeWords "here you are")
可以改写为:
capitalizeWords :: String -> String
capitalizeWords = unwords . map (\(f:rest) -> toUpper f : rest) . words
main = putStrLn $ capitalizeWords "here you are"
以下是解释:
可以在($)
函数中使用main
,因为可以将此运算符视为包含在括号内的右侧。
对于capitalizeWords
函数,首先可以简化:
capitalizeWords string = unwords $ map (\(f:rest) -> toUpper f : rest) (words string)
使用前面的解释。
同样,我们可以使用($)
:
capitalizeWords string = unwords $ map (\(f:rest) -> toUpper f : rest) $ words string
由于string
参数位于相等两侧的右侧,我们可以使用composition来删除此参数。所以我们得到上面显示的最终capitalizeWords
函数。
您可以详细了解($)
和(.)
运营商here。