Haskell:如果 x > 0,则将唯一字符分配给矩阵值
Haskell: Assigning unique char to matrix values if x > 0
所以我的程序目标是让它接收一个 Int 矩阵作为输入,程序将所有 > 0 的数字转换为唯一的顺序字符,而 0 转换为 '_'(无所谓,只是不在序列中的任何字符)。
例如
main> matrixGroupings [[0,2,1],[2,2,0],[[0,0,2]]
[["_ab"],["cd_"],["__e"]]
我能达到的最好成绩是
[["_aa"],["aa_"],["__a"]]
使用:
matrixGroupings xss = map (map (\x -> if x > 0 then 'a' else '_')) xss
据我所知,我遇到的问题是让程序记住它的最后一个值是什么,这样当值检查 > 0 时,它会选择行中的下一个字符。不过我这辈子都想不出怎么做。
如有任何帮助,我们将不胜感激。
你的问题是一个古老艺术的例子:用一连串的
标签。它至少可以追溯到 Chris Okasaki,我最喜欢的治疗方法是 Jeremy
长臂猿.
从这两个示例中可以看出,结构的方式可能有所不同
贴上标签。但在目前的情况下,我想最直接的方法就可以了。而在 Haskell
真的很短。让我们深入探讨。
食谱是这样的:
- 为您的矩阵定义多态类型。它必须是这样的,一个数字矩阵和一个
字符矩阵都是合法成员。
- 提供
Traversable
class 的实例。在许多情况下,它可能会自动派生。
- 根据自己的喜好选择一个 monad。一个简单的选择是
State
。 (其实这是我唯一的选择
能想到。)
- 在此 monad 中创建一个 action,将数字转换为字符。
- 用这个动作遍历一个矩阵。
我们做饭吧!
一个类型可能就这么简单:
newtype Matrix a = Matrix [[a]] deriving Show
完全有可能内部列表的长度不等——这种类型不会
保护我们免于制作 "ragged" 矩阵。这是糟糕的设计。但我要略过
现在。 Haskell 提供 endless depth 以求完美。这种类型足够好
我们这里的需求。
我们可以马上定义一个矩阵的例子:
example :: Matrix Int
example = Matrix [[0,2,1],[2,2,0],[0,0,2]]
定义一个Traversable
有多难? 0 很难。
{-# language DeriveTraversable #-}
...
newtype Matrix a = Matrix [[a]] deriving (Show, Functor, Foldable, Traversable)
Presto.
我们从哪里得到标签?这是副作用。函数到达某处,需要一个
标签流,取出头部,然后将尾巴放回 extra-dimensional 口袋中。一种
可以做到这一点的 monad 是 State
.
它是这样工作的:
label :: Int -> State String Char
label 0 = return '_'
label x = do
ls <- get
case ls of
[ ] -> error "No more labels!"
(l: ls') -> do
put ls'
return l
我希望代码能自我解释。当一个函数 "creates" 是一个 monadic 值时,我们称它为
"effectful",或给定 monad 中的 "action"。例如,print
是一个动作,
好吧,打印东西。这是一个效果。 label
也是一个动作,虽然在不同的
单子。自己比较看看。
现在我们准备做一道菜:
matrixGroupings m = evalState (traverse label m) ['a'..'z']
就是这个。
λ matrixGroupings example
Matrix ["_ab","cd_","__e"]
祝你胃口大开!
P.S. 我夺走了你所有的荣耀,这不公平。为了让事情再次变得有趣,我挑战你做一个练习:你能否定义一个 Traversable
实例,以另一种顺序标记矩阵——先按列,然后按行?
所以我的程序目标是让它接收一个 Int 矩阵作为输入,程序将所有 > 0 的数字转换为唯一的顺序字符,而 0 转换为 '_'(无所谓,只是不在序列中的任何字符)。
例如
main> matrixGroupings [[0,2,1],[2,2,0],[[0,0,2]]
[["_ab"],["cd_"],["__e"]]
我能达到的最好成绩是
[["_aa"],["aa_"],["__a"]]
使用:
matrixGroupings xss = map (map (\x -> if x > 0 then 'a' else '_')) xss
据我所知,我遇到的问题是让程序记住它的最后一个值是什么,这样当值检查 > 0 时,它会选择行中的下一个字符。不过我这辈子都想不出怎么做。
如有任何帮助,我们将不胜感激。
你的问题是一个古老艺术的例子:用一连串的 标签。它至少可以追溯到 Chris Okasaki,我最喜欢的治疗方法是 Jeremy 长臂猿.
从这两个示例中可以看出,结构的方式可能有所不同 贴上标签。但在目前的情况下,我想最直接的方法就可以了。而在 Haskell 真的很短。让我们深入探讨。
食谱是这样的:
- 为您的矩阵定义多态类型。它必须是这样的,一个数字矩阵和一个 字符矩阵都是合法成员。
- 提供
Traversable
class 的实例。在许多情况下,它可能会自动派生。 - 根据自己的喜好选择一个 monad。一个简单的选择是
State
。 (其实这是我唯一的选择 能想到。) - 在此 monad 中创建一个 action,将数字转换为字符。
- 用这个动作遍历一个矩阵。
我们做饭吧!
一个类型可能就这么简单:
newtype Matrix a = Matrix [[a]] deriving Show
完全有可能内部列表的长度不等——这种类型不会 保护我们免于制作 "ragged" 矩阵。这是糟糕的设计。但我要略过 现在。 Haskell 提供 endless depth 以求完美。这种类型足够好 我们这里的需求。
我们可以马上定义一个矩阵的例子:
example :: Matrix Int example = Matrix [[0,2,1],[2,2,0],[0,0,2]]
定义一个
Traversable
有多难? 0 很难。{-# language DeriveTraversable #-} ... newtype Matrix a = Matrix [[a]] deriving (Show, Functor, Foldable, Traversable)
Presto.
我们从哪里得到标签?这是副作用。函数到达某处,需要一个 标签流,取出头部,然后将尾巴放回 extra-dimensional 口袋中。一种 可以做到这一点的 monad 是
State
.它是这样工作的:
label :: Int -> State String Char label 0 = return '_' label x = do ls <- get case ls of [ ] -> error "No more labels!" (l: ls') -> do put ls' return l
我希望代码能自我解释。当一个函数 "creates" 是一个 monadic 值时,我们称它为 "effectful",或给定 monad 中的 "action"。例如,
print
是一个动作, 好吧,打印东西。这是一个效果。label
也是一个动作,虽然在不同的 单子。自己比较看看。现在我们准备做一道菜:
matrixGroupings m = evalState (traverse label m) ['a'..'z']
就是这个。
λ matrixGroupings example
Matrix ["_ab","cd_","__e"]
祝你胃口大开!
P.S. 我夺走了你所有的荣耀,这不公平。为了让事情再次变得有趣,我挑战你做一个练习:你能否定义一个 Traversable
实例,以另一种顺序标记矩阵——先按列,然后按行?