以下两个功能非常相似。它们从[String] n元素中读取[Int]或[Float]。如何计算公共代码?我不知道Haskell中支持将类型作为参数传递的任何机制。
readInts n stream = foldl next ([], stream) [1..n]
where
next (lst, x:xs) _ = (lst ++ [v], xs)
where
v = read x :: Int
readFloats n stream = foldl next ([], stream) [1..n]
where
next (lst, x:xs) _ = (lst ++ [v], xs)
where
v = read x :: Float
我处于Haskell的初级阶段,因此欢迎对我的代码发表任何评论。
答案 0 :(得分:16)
Haskell支持高度多态性。特别是
readAny n stream = foldl next ([], stream) [1..n]
where
next (lst, x:xs) _ = (lst ++ [v], xs)
where
v = read x
有类型
readAny :: (Enum b, Num b, Read a) => b -> [String] -> ([a], [String])
从而
readInts :: (Enum b, Num b) => b -> [String] -> ([Int], [String])
readInts = readAny
readFloats :: (Enum b, Num b) => b -> [String] -> ([Float], [String])
readFloats = readAny
你不需要专门化这种类型。 Haskell会自动推断出最常见的类型,readAny
这里可以做你想要的。
无法在Haskell中将类型作为参数传递。你很少需要。对于那些有必要的情况,您可以通过传递具有所需类型的值来模拟行为。
Haskell有“返回类型多态”,所以你真的不应该担心“传递类型” - 很可能函数会在你告诉他们的情况下做你想做的事。
答案 1 :(得分:9)
基本上你想要的是不明确声明类型。相反,推迟声明类型并让推理引擎为您接管。另外,我认为你正在将折叠与地图混为一谈。这就是我接近它的方式。
readList' :: Read a => [String] -> [a]
readList' = map read
ints = readList' ["1", "2"] :: [Int] -- [1, 2]
floats = readList' ["1.0", "2.0"] :: [Float] -- [1.0, 2.0]
要仅从流中读取n个内容,请使用take