【发布时间】:2016-09-30 05:44:53
【问题描述】:
这两个功能几乎相同:
dig :: MappingClassifierM FileSummary IO Partitioner -> Conduit (Cluster Partitioner FileSummary) IO (Cluster Partitioner FileSummary)
dig classifier =
await >>= \case
Nothing -> return ()
Just ( Cluster clusterKey clusterValue ) -> do
categories <- liftIO $ classify classifier clusterValue
if (length clusterValue == length categories)
then do
yield $ Cluster clusterKey clusterValue
dig classifier
else do
mapM_ (yield . cluster) categories
dig classifier
where
cluster (key, val) = Cluster (key : clusterKey) val
classify = classifyM
dig' :: BinaryClassifierM FileSummary IO -> Conduit (Cluster Partitioner FileSummary) IO (Cluster Partitioner FileSummary)
dig' classifier =
await >>= \case
Nothing -> return ()
Just ( Cluster clusterKey clusterValue ) -> do
categories <- liftIO $ classify classifier clusterValue
if (length clusterValue == length categories)
then do
yield $ Cluster clusterKey clusterValue
dig' classifier
else do
mapM_ (yield . cluster) categories
dig' classifier
where
cluster = Cluster (Content : clusterKey)
classify = classifyBinary
唯一的区别在于 where 子句中定义的函数。
以下限制适用:
-
classify函数取决于作为第一个参数传递的分类器的“类型”。 -
cluster函数取决于分类器的实际实现。
我想概括这两个函数,以便创建一个处理这两个实现以避免重复的单个函数。
我不知道我的方向是否正确。根据我迄今为止对 Haskell 的有限了解,我认为我必须创建一个类“分类器”,其中 BinaryClassifier 和 MappingClassifierM 将是其实例,但是当我尝试实现它时遇到了几个编译错误.
所以,我的问题是:有经验的 Haskell 程序员如何概括这两个函数以避免重复?
对于其他上下文,以下是我试图概括的两种不同情况的相关类型签名:
type MappingClassifierM a m k = a -> m k
classifyM :: (Monad m, Ord k) => MappingClassifierM a m k -> [a] -> m [(k, [a])]
dig :: MappingClassifierM FileSummary IO Partitioner -> Conduit (Cluster Partitioner FileSummary) IO (Cluster Partitioner FileSummary)
type BinaryClassifierM a m = a -> a -> m Bool
classifyBinary :: Monad m => BinaryClassifierM a m -> [a] -> m [[a]]
dig' :: BinaryClassifierM FileSummary IO -> Conduit (Cluster Partitioner FileSummary) IO (Cluster Partitioner FileSummary)
【问题讨论】:
-
只需将
dig设为高阶函数,并将cluster和classify函数作为参数传入即可。 -
变量
categories的类型在dig和dig'之间似乎不同 - 对吗? -
一个你可能喜欢的小把戏:
\case Nothing -> return (); Just p -> e也可以写成traverse_ (\p -> e)。 -
@ErikR,你是对的,类别的类型不同。在每种情况下,
categories的类型都是classify函数返回的类型。差异在cluster函数中处理
标签: haskell functional-programming