将类型作为Haskell中函数的参数传递?

时间:2012-04-06 04:52:39

标签: haskell types

以下两个功能非常相似。它们从[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的初级阶段,因此欢迎对我的代码发表任何评论。

2 个答案:

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