1

私は Haskell 用の Hadoop ライブラリに取り組んでいますが、存在型の型付けと型クラスに関するいくつかの問題に遭遇し、解決できないようです。私のコードは次のとおりです。

type Mapper k1 v1 k2 v2 = k1 -> v1 -> IO [(k2,v2)]

type Reducer k1 v1 k2 v2 = k1 -> [v1] -> IO [(k2,v2)]

data Iteration k1 v1 k3 v3 = forall k2 v2 . Iteration (Mapper k1 v1 k2 v2) (Reducer k2 v2 k3 v3)

data Job k1 v1 k3 v3 = EmptyJob | forall k2 v2 . ConsJob (Iteration k1 v1 k2 v2) (Job k2 v2 k3 v3)

type IterationNumber = Int
data IterationPhase = IterationMapper | IterationReducer

runJobIteration :: Job k1 v1 k2 v2 -> IterationNumber -> IterationPhase -> IO ()
runJobIteration EmptyJob _ _ = return ()
runJobIteration (ConsJob (Iteration m r) _) 0 IterationMapper = runMapper m
runJobIteration (ConsJob (Iteration m r) _) 0 IterationReducer = runReducer r
runJobIteration (ConsJob (Iteration m r) j) i p = runJobIteration j (i-1) p

runMapper :: (Parsable k1, Parsable v1, Showable v2, Showable k2) => Mapper k1 v1 k2 v2 ->   IO ()
runMapper mapper = do
    contents <- getContents
    mapOutput <- mapM (uncurry mapper . parseKeyValue) $ lines contents
    mapM_ putStrLn $ map showKeyValue $ concat mapOutput


runReducer :: (Parsable k1, Parsable v1, Eq k1, Eq v1, Showable v2, Showable k2) =>    Reducer k1 v1 k2 v2 -> IO ()
runReducer reducer = do
    contents <- getContents
    reduceOutput <- mapM (uncurry reducer) $ groupMapOutput $ map parseKeyValue $ lines contents
    mapM_ putStrLn $ map showKeyValue $ concat reduceOutput

parseKeyValue :: (Parsable k, Parsable v) => String -> (k,v)
parseKeyValue = (parse *** parse) . split (== '\t')


split :: (a -> Bool) -> [a] -> ([a], [a])
split p xs = let (group, rest) = break p xs
             in (group, tail rest)

showKeyValue :: (Showable k, Showable v) => (k,v) -> String
showKeyValue (k,v) = showit k ++ "\t" ++ showit v

groupMapOutput :: (Eq k, Eq v) => [(k,v)] -> [(k,[v])]
groupMapOutput kvs = groupMapOutput' kvs []
groupMapOutput' kvs gs
    | kvs == [] = gs
    | otherwise = groupMapOutput' rest (gs ++ [(k, map snd group)])
        where 
            k = fst (head kvs)
            (group, rest) = span ((== k) . fst) kvs

上記のコードを読み込もうとすると、常に次のエラーが発生します。

No instances for (Showable k4,
                    Showable v4,
                    Parsable v1,
                    Parsable k1)
    arising from a use of `runMapper'
  In the expression: runMapper m
  In an equation for `runJobIteration':
      runJobIteration (ConsJob (Iteration m r) _) 0 IterationMapper
        = runMapper m

型クラスをデータ コンストラクターに追加しようとしましたが、うまくいかないようです。また、型を非表示にする AnyMapper データ型を作成しようとしましたが、それも機能しませんでした。これをエレガントに解決する方法を知っている人はいますか?

4

1 に答える 1

1

わかりました、すべての関数とデータ型を調べて、コンパイルするまで必要な型制約を追加することで、なんとか解決しました。主な問題は、存在部分にない型の型制約を含める必要があることのようです。ただし、コンパイラはこれらの型に異なる名前を付けたため、少し混乱しました。参考までに、最も重要な変更点を以下に示します。いずれにせよ、これらの型制約の長いリストの代わりに、型クラスに切り替えるつもりです。


data Iteration k1 v1 k3 v3 = forall k2 v2 . (Eq k2, Eq v2, Showable k2, Showable v2, Parsable k2, Parsable v2) => Iteration (Mapper k1 v1 k2 v2) (Reducer k2 v2 k3 v3)
data Job k1 v1 k3 v3 = EmptyJob | forall k2 v2 . (Eq k2, Eq v2, Showable k2, Showable v2, Parsable k2, Parsable v2) => ConsJob (Iteration k1 v1 k2 v2) (Job k2 v2 k3 v3)
runJobIteration :: (Parsable k1, Parsable v1, Parsable k2, Parsable v2, Showable k1, Showable v1, Showable k2, Showable v2) => Job k1 v1 k2 v2 -> IterationNumber -> IterationPhase -> IO ()

于 2013-01-23T09:48:41.027 に答える