8

次の 2 つの機能は非常によく似ています。[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 の初心者レベルなので、コードに関するコメントは大歓迎です。

4

2 に答える 2

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 には「戻り型のポリモーフィズム」があるため、「型を渡す」ことについて心配する必要はありません。

于 2012-04-06T05:01:16.900 に答える
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

于 2012-04-06T05:11:41.650 に答える