不知道如何使用.和 $ 运算符在哈斯克尔



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

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]

我对如何使用这些运算符有点困惑。

我没有看到在此代码中使用($)(.)的方法。

但是,您可以按如下方式简化代码:

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 参数位于相等式两侧的右侧,因此我们可以使用组合来删除此参数。所以我们得到了上面显示的最终capitalizeWords函数。

您可以在此处了解有关($)(.)运算符的更多信息。

有一些工具可以帮助您编写无点函数,如 hlint 和 pointfree。

最新更新