首页 > 解决方案 > Haskell 标志模式

问题描述

我是 Haskell 的一个非常新的用户,并且在一些工作中陷入了困境。我被分配了制作一个标志模式函数的任务,它会产生这样的东西 -

这是一个链接到它应该是什么样子的图像 来描述它,它基本上是一个空心矩形,中间有一个 X 用 * 产生

唯一的问题是我不太清楚如何几乎完全使用haskell,尤其是坐标甚至if-then-else。

这是我到目前为止所拥有的,我几乎被困在 if then else 部分。任何帮助将非常感激!

flagpattern :: Int -> String
flagpattern a
  | a <= 4 = ""
  | otherwise = fill (grid a) a

grid :: Int -> [(Int, Int)]
grid a = [(x, y)| x<- [0..a], y<-[0..a]]

fill :: [(Int, Int)] -> Int -> String
fill [(x:xs,y:ys)] a
if fst (x,y) == 0 then
    if snd (x,y) < a then "*" ++ fill [(xs,ys)]
    else "*\n" ++ fill [(xs,ys)]
else
    if fst (x,y) == a then
        if snd (x,y) < a then "*" ++ fill [(xs,ys)]
        else "*\n" ++ fill [(xs,ys)]
    else 
        if fst (x,y) + snd (x,y) == a then
            if fst (x,y) == a then "*\n" ++ fill [(xs,ys)]
            else "*" ++ fill [(xs,ys)]
        else " " ++ fill [(xs,ys)]

标签: haskell

解决方案


我在您发布的代码中看到的主要问题是缺少=定义fill和错误缩进的正文。修复:

fill :: [(Int, Int)] -> Int -> String
fill [(x:xs,y:ys)] a =   -- NOTE: need an `=` here
  -- NOTE: function body needs to be indendented
  if fst (x,y) == 0 then
      if snd (x,y) < a then "*" ++ fill [(xs,ys)]
      else "*\n" ++ fill [(xs,ys)]
  else
      if fst (x,y) == a then
          if snd (x,y) < a then "*" ++ fill [(xs,ys)]
          else "*\n" ++ fill [(xs,ys)]
      else 
          if fst (x,y) + snd (x,y) == a then
              if fst (x,y) == a then "*\n" ++ fill [(xs,ys)]
              else "*" ++ fill [(xs,ys)]
          else " " ++ fill [(xs,ys)]

摆脱了解析错误并引入了大约十亿个类型错误。在您的定义中fill

fill [(x:xs,y:ys)] a = ...

第一个参数模式不是匹配元组列表的正确方法:

[(0,0),(0,1),...]

相反,您想像这样从其余元组中剥离第一个元组:

fill ((x,y):rest) a = ...

并传递rest给递归fill调用。我认为,您还忘记了将第二个参数传递a给递归fill调用。修复该问题后,您的函数如下所示:

fill :: [(Int, Int)] -> Int -> String
fill ((x,y):rest) a =
  if fst (x,y) == 0 then
      if snd (x,y) < a then "*" ++ fill rest a
      else "*\n" ++ fill rest a
  else
      if fst (x,y) == a then
          if snd (x,y) < a then "*" ++ fill rest a
          else "*\n" ++ fill rest a
      else
          if fst (x,y) + snd (x,y) == a then
              if fst (x,y) == a then "*\n" ++ fill rest a
              else "*" ++ fill rest a
          else " " ++ fill rest a

这种类型的检查,虽然flagpattern 7在输出一些不正确的输出后以不匹配的模式崩溃:

> flagpattern 7
"********\n      *      *      *      *      *      *      ********\n*** Exception: Flag.hs:(19,1)-(31,33): Non-exhaustive patterns in function fill

但也许这会帮助你继续工作。

另外,请注意在 Haskell 中,表达式[0..a]包括两个端点:

> [0..7]
[0,1,2,3,4,5,6,7]

因此,如果您希望返回 7x7 网格而不是 8x8 网格,您可能希望使用其中一个[0..a-1][1..a]ingrid对测试进行相应的更改。fillflagPattern 7


推荐阅读