类似Control.Foldl的数据类型

时间:2017-08-14 12:55:24

标签: haskell arrows

我正在修改提供CategoryArrow实例的Control.Foldl数据类型。 我的定义如下:

data FoldlCat a b = forall x c. FoldlCat (x -> a -> c) x (c -> x) (c -> b)

其中第一个参数代表“步”功能(savedState -> newInput -> intermediateValue),第二个代表初始savedState,第三个代表“保存”功能(intermediateValue -> savedState),最后一个是一个“提取”功能(intermediateValue -> newOutput)。

map (*10) . scanl (+) 0之类的内容可以表示为FoldlCat (+) 0 id (*10)

保存功能的主要目的是促进idarr的定义,如下所示:

id = FoldlCat (\_ x -> x) () (const ()) id

现在我试图想出一个ArrowLoop的实例是不成功的。我看不出有任何理由不可能,但是,我对fix这样的概念感到不舒服。到目前为止,我最好的尝试是typechecks,但永远循环。

instance ArrowLoop FoldlCat where
  loop (FoldlCat s b a d) = FoldlCat step b (a . snd) fst where
    step x = loop' d (s x)
    loop' f g x = let ~(v, ~(c,d)) = let ~v = g (x,d) in (v, f v)
                  in (c, v)

如果有人可以分享他们定义这样一个实例的方法(如果它可以在(.)内的累加器中使用严格的元组),或者解释为什么这是不可能的,或者解释为什么,我将不胜感激。 FoldlCat更好的结构。

{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE Arrows #-}

import Data.List (unfoldr)
import Prelude hiding (id, (.))
import Control.Category
import Control.Arrow

-- | FoldlCat  step init save export
data FoldlCat a b = forall x c. FoldlCat (x -> a -> c) x (c -> x) (c -> b)

mapCat :: (a -> b) -> FoldlCat a b
mapCat f = FoldlCat (\_ x -> x) () (const ()) f

evalList :: FoldlCat t b -> [t] -> [b]
evalList (FoldlCat s b a d) ys = unfoldr stepan (b, ys) where
    stepan (accVal, (x:xs))  = Just (nexVal, (newAcc, xs)) where
      newMeta = s accVal x
      newAcc  = a newMeta
      nexVal  = d newMeta
    stepan (accVal, [])      = Nothing

delay :: b -> FoldlCat b b
delay def = FoldlCat (,) def snd fst

instance Category FoldlCat where
  id = mapCat id

  (.) (FoldlCat step2 begin2 acc2 done2) (FoldlCat step1 begin1 acc1 done1) =
      let step = \(a, b) y -> let !a' = step1 a y
                                  !b' = step2 b (done1 a') in (a', b')
          begin = (begin1, begin2)
          acc   = \(x, y) -> ((acc1 x), (acc2 y))
          done = \(a, b) -> done2 b
      in
        FoldlCat step begin acc done

instance Arrow FoldlCat where
  arr f = mapCat f

  first (FoldlCat s b a d) = FoldlCat step b (a . fst) extF where
    step = (\a (x, y) -> (s a x, y))
    extF = (\(ok, y) -> (d ok, y))

instance ArrowLoop FoldlCat where
  loop (FoldlCat s b a d) = FoldlCat step b (a . snd) fst where
    step x = loop' d (s x)
    loop' f g x = let ~(v, ~(c,d)) = let ~v = g (x,d) in (v, f v)
                  in (c, v)

chaseFromZero = proc target -> do
  rec let step = signum (target - x)
      x <- FoldlCat (+) 0 id id <<< delay 0 -< step
  id -< x

main = print $ evalList chaseFromZero [1..5]

编辑虽然我不确定它的工作原理和原因,但在step中修复(.)的严格性(即删除let !a' = step1 a y中的爆炸)似乎会使这个例子工作。

0 个答案:

没有答案