纯脚本中的惯用 Haskell RLE
Idiomatic Haskell RLE in Purescript
所以,我试图通过转换我从 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]
我很快了解到:
- 没有
[]
shorthand;
- 没有
(,)
个元组;
- 我们需要用显式
forall
; 来量化多态函数
- 没有与
Array
类型的 cons (:)
运算符匹配的模式;
- ...
所以问题来了:用 Purescript 编写上述解决方案的最惯用方法是什么?
到目前为止这是我自己的回答(虽然不完全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
There's no [] shorthand
在 PureScript 中我们显式调用类型构造函数 List
There's no (,) tuples
在 PureScript 中,我们要么使用 Tuple
类型,要么另一种常见模式是使用具有描述性名称的记录,就像我在下面的解决方案中所做的那样。
We need to quantify polymorphic functions with an explicit forall
是
No pattern matching with cons (:) operator for the Array type
我们可以在 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
所以,我试图通过转换我从 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]
我很快了解到:
- 没有
[]
shorthand; - 没有
(,)
个元组; - 我们需要用显式
forall
; 来量化多态函数
- 没有与
Array
类型的cons (:)
运算符匹配的模式; - ...
所以问题来了:用 Purescript 编写上述解决方案的最惯用方法是什么?
到目前为止这是我自己的回答(虽然不完全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
There's no [] shorthand
在 PureScript 中我们显式调用类型构造函数 List
There's no (,) tuples
在 PureScript 中,我们要么使用 Tuple
类型,要么另一种常见模式是使用具有描述性名称的记录,就像我在下面的解决方案中所做的那样。
We need to quantify polymorphic functions with an explicit forall
是
No pattern matching with cons (:) operator for the Array type
我们可以在 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