关于Haskell运算符优先级和函数组成的说明

Explanation about Haskell operator precedence and function composition

我需要一些帮助来理解 "List Replication" Hackerrank 挑战的 Haskell 模板。我不明白函数执行的顺序。

f = concatMap . replicate

-- This part handles the Input and Output and can be used as it is. 
main :: IO ()
main = getContents >>=
       mapM_ print . (\(n:arr) -> f n arr) . map read . words

getContents 函数应该生成一个 IO String,如 "2\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10"。我大致了解接下来会发生什么,但我不了解顺序和优先级。我尝试在 ghci 中执行 words "2\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10 并将结果输入 map read。但后来我得到了结果"[*** Exception: Prelude.read: no parse"。如果我尝试 map read . words "2\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10",我会得到结果 "Couldn't match expected type ‘a -> [String]’ with actual type ‘[String]’"。整个组合的main函数怎么没有报错?

如果有人能帮助我理解整个主要功能,我将不胜感激。尤其是哪些函数以何种顺序和哪些输入执行,以及我如何将它分成更小的(工作!)部分以更好地理解它。

非常感谢!

在 GHCi 提示符下定义

g = (\(n:arr) -> f n arr)
 where
 f = concatMap . replicate

我们将派生类型返回为 g :: [Int] -> [Int]。这将 map readread 的类型(馈入 g)定义为 String -> Int,并且一切正常。以更易读的形式可以更容易理解,

g :: [Int] -> [Int]
g (n:arr) = concatMap (replicate n) arr

类型 Int 派生自 n :: Int,因为 replicate :: Int -> a -> [a]arr(n:arr) :: [Int] 的类型都源于此,因为 Haskell 列表是同类的,即具有相同类型的所有元素。

最常见的 read 类型是 read :: Read a => String -> a。事实上 IntRead 类型 class.

但是如果我们不知道这是 IntDouble 还是其他东西怎么办?然后 read 不知道要解析哪种格式,所以我们得到 "read: no parse" 错误消息。

这就是我们尝试

时发生的情况
(map read . words) "2\n3\n4\n"  =  map read $ words "2\n3\n4\n" 
                                =  map read (words "2\n3\n4\n")

当我们打开括号时,$ 出现在那里而不是 .。由于运算符优先级,您的 main 函数实际上是

main :: IO ()
main = getContents >>=
       (mapM_ print . (\(n:arr) -> f n arr) . map read . words)
     = getContents >>= (\s -> 
       (mapM_ print . g                     . map read . words) s)
     = getContents >>= (\s -> 
        mapM_ print $ g                     $ map read $ words  s)

像你那样使用 . 而不是 $ 是错误的,因为省略那些括号是错误的,会导致其他与函数相关的错误消息,因为 . 期望function 作为其右侧的参数,但 ["2","3","4"] 不是函数。