不知道怎么用。和Haskell中的$运算符

时间:2014-12-30 03:10:06

标签: haskell function-composition

我不确定如何实施.$运算符来简化以下定义:

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]

我对如何使用这些运营商感到有点困惑。

1 个答案:

答案 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

有些工具可以帮助您编写像hlintpointfree这样的无点功能。