【问题标题】:Idiomatic Haskell RLE in PurescriptPurescript 中的惯用 Haskell RLE
【发布时间】:2017-03-08 23:56:45
【问题描述】:

所以,我正在尝试通过转换我从 99 Haskell Problems 获得的一些 Haskell 代码来学习 Purescript,并很快陷入了我知道如何解决它的情况,但它只是 太丑了™。这是问题 10、11 和 12 的 Haskell 代码;基本上是一些 RLE 编码和解码功能:

-- Problem 10

rle :: Eq α => [α] -> [(Int, α)]
rle [] = []
rle (x:xs) = let (h, t) = span (== x) xs 
              in (length h + 1, x) : rle t

-- Problem 11

data RleItem α = Pair Int α | Single α deriving (Show)

encode :: Eq α => [α] -> [RleItem α]
encode = map unpack . rle 
   where unpack (1, x) = Single x
         unpack (y, x) = Pair y x

-- Problem 12

decode :: [RleItem α] -> [α]
decode = concatMap unroll
  where unroll (Pair y x) = replicate y x
        unroll (Single x) = [x] 

我很快就知道了:

  • 没有[] 速记;
  • 没有(,) 元组;
  • 我们需要用明确的forall 量化多态函数;
  • 没有与 cons (:) 运算符的模式匹配 Array 类型;
  • ...

那么问题来了:在 Purescript 中编写上述解决方案最惯用的方法是什么

【问题讨论】:

    标签: haskell purescript


    【解决方案1】:

    没有 [] 速记

    在 PureScript 中,我们显式调用类型构造函数 List

    没有 (,) 元组

    在 PureScript 中,我们要么使用 Tuple 类型,要么另一种常见的模式是使用具有描述性名称的记录,就像我在下面的解决方案中所做的那样。

    我们需要用明确的 forall 量化多态函数

    是的

    没有与 Array 类型的 cons (:) 运算符匹配的模式

    我们可以用:List 类型进行模式匹配。与Array 的头部匹配的模式几乎不是一个好主意,因为它对性能非常不利。

    我已使用上述要点将您的解决方案翻译成 PureScript。该示例也可以在以下位置试用和运行:http://try.purescript.org/?gist=f45651a7f4d134d466d575b1c4dfb614&backend=core

    -- Problem 10
    
    rle :: forall a. (Eq a) => List a -> List {repetitions :: Int, value :: a}
    rle Nil = Nil
    rle (x:xs) = case span (_ == x) xs of
      {init: h, rest: t} -> {repetitions: length h + 1, value: x} : rle t
    
    -- Problem 11
    
    data RleItem a = Pair Int a | Single a
    
    encode :: forall a. Eq a => List a -> List (RleItem a)
    encode = map unpack <<< rle 
       where 
        unpack = case _ of
          {repetitions: 1, value} -> Single value
          {repetitions, value} -> Pair repetitions value
    
    -- Problem 12
    
    decode :: forall a. List (RleItem a) -> List a
    decode = concatMap unroll
      where unroll (Pair y x) = replicate y x
            unroll (Single x) = singleton x 
    

    【讨论】:

      【解决方案2】:

      到目前为止,这是我自己的答案(尽管不完全是 1:1),但我不希望接受它:

      data RleItem α = Pair Int α | Single α
      
      encode :: forall α. (Eq α) => List α -> List (RleItem α)
      encode Nil = Nil
      encode p@(x:_) = let s = span ((==) x) p in
        pack (length s.init) : encode s.rest where
          pack 0 = Single x
          pack y = Pair y x
      
      decode :: forall α. List (RleItem α) -> List α
      decode = (=<<) unpack where
        unpack (Single x) = pure x
        unpack (Pair y x) = replicate y x
      

      【讨论】:

        猜你喜欢
        • 2022-12-02
        • 1970-01-01
        • 2020-08-31
        • 2020-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-08
        • 1970-01-01
        相关资源
        最近更新 更多