- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
Stream (Of a) m r -> Stream (Of a) m s -> Str-6ren">
目标是概括 Streaming.merge
函数,
merge :: (Monad m, Ord a) => Stream (Of a) m r -> Stream (Of a) m s -> Stream (Of a) m (r, s)
到任意数量的源流。策略是使用 Data.Heap.Heap
的Stream (Of a) m r
按 a
排序。 IE。 bigMerge
会有签名
bigMerge :: (Monad m, Ord a) => [Stream (Of a) m r] -> Stream (Of a) m [r]
(该列表也可以替换为 Heap
。)
我拥有的是一种相当邪恶的混合物,不太正确。就这样:
为了完整,首先关闭导入:
import qualified Data.Heap as H
import Data.Heap (Heap)
import Data.List (sortBy)
import Data.Function (on)
import Streaming
import qualified Streaming.Prelude as S
import Streaming.Internal (Stream(..)) -- shouldn't!
为了使用Heap
Ord
类的一个元素需要:
data Elt a m r = Elt Int (Maybe a) (Stream(Of a) m r)
额外的Int
引入了在输入列表中携带流的索引,以便返回 [r]
可以按正确的顺序使用元素构建。 Maybe a
携带流的当前值。
Eq
和Ord
实例是:
instance Eq a => Eq (Elt a m r) where
(Elt i ma _) == (Elt i' ma' _) =
if i == i' then error "Internal error: Index clash in =="
else ma == ma'
instance Ord a => Ord (Elt a m r) where
(Elt i ma s) <= (Elt i' ma' s') | i==i' = error "Internal error: Index clash in <="
| otherwise = cmp (i, ma, s) (i', ma', s')
where
cmp _ (_, Nothing, Return _) = True
cmp (_, Nothing, Return _) _ = False
cmp (i, Just a, _) (i', Just a', _) = if a == a' then i <= i' else a <= a'
cmp (i, _, _) (i', _, _) = i <= i'
基本上,任何东西都是<=
一个Return
,所有其他情况都使用 a
和/或i
排序Elt
s。 (errors
用于调试目的。)
一些辅助函数 make Elt
来自Stream
和Heap
来自 Stream
的列表.
eltFromStream :: (Monad m, Ord a) => Int -> Stream (Of a) m r -> m (Elt a m r)
eltFromStream i (Return r) = return $ Elt i Nothing (Return r)
eltFromStream i (Effect m) = do
stream' <- m
return $ Elt i Nothing stream'
eltFromStream i (Step (a :> rest)) = return $ Elt i (Just a) rest
heapFromStreams :: (Monad m, Ord a) => [Stream (Of a) m r] -> m (Heap (Elt a m r))
heapFromStreams strs = H.fromList <$> (sequence $ fmap (uncurry eltFromStream) (zip [0..] strs))
核心部分是loop
功能
loop :: (Monad m, Ord a) => Heap (Elt a m r) -> m (Heap (Elt a m r))
loop h = do
let (Elt i ma s, h') = unsafeUncons h
elt <- case s of
Return r -> return $ Elt i Nothing (Return r)
Effect m -> Elt i Nothing <$> m
Step (a :> rest) -> return $ Elt i (Just a) rest
return $ H.insert elt h'
厚脸皮的unsafeUncons
正在
unsafeUncons :: Heap a -> (a, Heap a)
unsafeUncons h = case H.uncons h of
Nothing -> error "Internal error"
Just x -> x
loop
函数用于 heapMerge
这变成了Heap
进入Stream
heapMerge :: (Monad m, Ord a) => Heap (Elt a m r) -> Stream (Of a) m [r]
heapMerge h = case (ma,s) of
(Nothing, Return _) -> Return $ getRs h
(_, Effect m) -> error "TODO"
(Just a, _) -> do
h' <- lift $ loop h
Step (a :> heapMerge h')
where
Elt i ma s = H.minimum h
getRs
只需组装Return
值放入列表
getRs :: (Monad m, Ord a) => Heap (Elt a m r) -> [r]
getRs h = snd <$> sortBy (compare `on` fst) (map f (H.toUnsortedList h))
where
f :: Monad m => Elt a m r -> (Int, r)
f (Elt i _ (Return r)) = (i,r)
f _ = error "Internal error: Call getR only after stream has finished!"
然后,最后,
bigMerge :: (Monad m, Ord a) => [Stream (Of a) m r] -> Stream (Of a) m [r]
bigMerge streams =
if null streams then Return []
else do
h <- lift $ heapFromStreams streams
heapMerge h
这很复杂,Effect
没有正确对待,它依赖Return
, Step
, Effect
而不是inspect
和next
。它确实会在简单的输入上产生正确的结果,例如
s1 = S.each [2,4,5::Int]
s2 = S.each [1,2,4,5::Int]
s3 = S.each [3::Int]
S.print $ merge [s1,s2,s3]
我确信有一种方法可以正确且更惯用地执行此操作。一方面,Maybe a
在 Elt
可能是多余的,我可以做 (Stream (Of a) m r)
Ord
的一个实例直接,如果 Effect
只是模式匹配,没有执行,那么这应该没问题。但是Stream (Of (Heap (Stream (Of a) m r, Int))) (Heap (Int,r))
看起来很奇怪。 “带索引的流”IStream a m r = IStream Int ((Heap (Stream (Of a) m r) deriving Functor
是r
中的一个仿函数,因此,适当的==
和<=
,我会看 Stream (IStream a m) m (Heap (Int, r))
?
streaming
的这个功能方面图书馆对我来说仍然有点困惑,所以任何帮助将不胜感激。
最佳答案
bigMerge
的签名看起来非常像 sequenceA
的签名来自Data.Traversable
:
sequenceA :: Applicative f => [f r] -> f [r]
问题当然是我们不能对 Stream
使用标准的 Applicative
实例,因为它是连接而不是合并。但我们可以尝试通过新类型创建我们自己的实例:
{-# LANGUAGE DeriveFunctor #-}
import Streaming
import qualified Streaming.Prelude as S
newtype MergeStream a m r =
MergeStream { getMergeStream :: Stream (Of a) m r } deriving Functor
-- BEWARE! Only valid for ORDERED streams!
instance (Monad m, Ord a) => Applicative (MergeStream a m) where
pure x = MergeStream (pure x)
MergeStream f <*> MergeStream x = MergeStream (uncurry ($) <$> S.merge f x)
现在,使用示例中的 s1
、s2
和 s3
以及标准 Traversable
函数:
ghci> S.toList_ $ getMergeStream . traverse MergeStream $ [s1,s2,s3]
[1,2,2,3,4,4,5,5]
这似乎有效。也就是说,出于效率原因,您尝试使用 Stream
内部结构和堆来实现 bigMerge
可能仍然是值得的。
关于haskell - 概括Haskell "Streaming"库的合并功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59170314/
我正在寻找一种简单的方法来编写函数 mapAndUnzip :: (Functor f) => (a -> (b,c)) -> f a -> (f b, f c) 我并不完全相信 Functor是一个
我的代码是这样的: if(country == china) { getCNData(); } else { getDefaultDataForallCountries(); } 现在我需要为其他国家
在处理使用类型类模式的 Scala 项目时,我遇到了语言如何实现模式的严重问题:由于 Scala 类型类实现必须由程序员而不是语言管理,因此任何变量属于一个类型类永远不会被注解为父类型,除非它的类型类
我正在尝试在 R 中创建一个公式,其形式为 输出~Var1+Var2+Var3 用于模型。它的工作方式似乎是你给你想要预测的变量名,波浪号,你想用作预测变量的变量名,然后在后面的参数中你给出包含这些变
我正在使用一堆类型的宏: #define Q31_TO_Q30 (31-30) #define Q31_TO_Q20 (31-20) #define Q25_TO_Q15 (25-15) etc. 我
为了提高工作效率,我使用以下函数来了解我必须为哪些函数设置别名,因为我最常使用它们: function mu() { if [[ $# -eq 0 ]]; then histo
我有几个文本框。我想在每次按下回车键时将用户指向下一个文本框。文本框已正确设置 Tabindex。 我有这样的东西: private void textBox_Description_KeyPres
有什么方法可以将列约束应用于我的所有 GridPanes 列。我有各种 GridPane 控件,我希望它们共享以下列约束: 可以用css来实现吗? 编辑 我最终做了这样的事情。但它不起作用(我的列宽
我正在尝试在 Swift、Xcode 7.3(所以是 Swift 2.2)中创建一个通用类,但我似乎无法让它通过编译器: protocol Struct1Protocol { } struct Str
我正在做一个 JavaScript 游戏作业,只是尝试玩一下 Canvas 。我的任务是使用激光源、镜子和目标物体进行激光游戏。 我刚刚做了一个丑陋的硬编码示例: 'use strict'; func
我正在尝试从任何公共(public) REST API 获取响应并对其进行处理(解析并放入数据结构)。从 API 获取此响应时,我想使用一些分页功能。我提到了this ,该问题讨论了特定 API 的分
我有一个与 Guice 的机器人腿示例非常相似的用例,只是我不知道我有多少条“腿”。因此我不能使用机器人腿示例所需的注释。 我希望使用 Guice 的 Multibindings 扩展将所有这些“腿”
(按标题道歉,我不能做得更好) 我的问题是找到一些通用的结构或“标准”函数来执行下一件事: xmap :: (a -> b) -> f a -> g b 然后,我们不仅可以映射元素,还可以映射整个结构
haskell 中是否有一个函数可以概括 Maybe 和 Either 函数? 例如,我正在想象一个这样的函数: generalizedFunc :: SOMETHING m => b -> (a -
下面函数模板的目标是取任意unordered_map并产生一个新的unordered_map与 key_type和 mapped_type倒。下面的函数适用于 std::unorderd_map .我
我是一名优秀的程序员,十分优秀!