关于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 read
中 read
的类型(馈入 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
。事实上 Int
在 Read
类型 class.
但是如果我们不知道这是 Int
、Double
还是其他东西怎么办?然后 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"]
不是函数。
我需要一些帮助来理解 "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 read
中 read
的类型(馈入 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
。事实上 Int
在 Read
类型 class.
但是如果我们不知道这是 Int
、Double
还是其他东西怎么办?然后 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"]
不是函数。