【问题标题】:Is there a "continue" in Haskell?Haskell中是否有“继续”?
【发布时间】:2017-10-11 16:39:43
【问题描述】:

我最近开始学习 Haskell,目前正在尝试编写基本的 Haskell 函数。

我编写了一个名为intToRoman 的函数,它应该将整数转换为罗马数字。它将整数列表中的数字 (1400 ->[1,4,0​​,0]) 相除,然后根据列表的帐户长度将每个数字转换为罗马数字,以确定是一千还是一百。

但是,它不会停止并检查零。例如,数字 1400 将返回:

 MCD** Exception: Map.!: given key is not an element in the map
 CallStack (from HasCallStack)

这是代码本身:

mapInttoRoman:: M.Map Int String
mapInttoRoman = M.fromList
          [(1,"I"),(4,"IV"),(5,"V"),(9,"IX"),(10,"X"),(40,"XL")
          ,(50,"L"),(100,"C"),(400,"CD"),(900,"CM"),(500,"D"),(1000,"M")]

listOfInt :: Int -> [Int]
listOfInt 0 = [ ]
listOfInt c = listOfInt(c`div`10) ++ [c`mod`10]

duplicate :: String -> Int -> String
duplicate string n = concat $ replicate n string

intToRoman :: Int -> String
intToRoman 0 = ""
intToRoman c = createInt x (len-1)
 where x = listOfInt c
       len = length x
       createInt y xz = findRoman (head y) xz ++ createInt(drop 1 y)(xz-1)
        where findRoman b l
               | l < 1      = mapInttoRoman M.! b
               | b == 0     = " "
               | l == 3     = duplicate (mapInttoRoman M.! (10^l)) b
               | b == 1     = mapInttoRoman M.! (10^l)
               | otherwise  = mapInttoRoman M.! (b*10^l)

【问题讨论】:

  • 您的 | b == 0 = " " 案例无法捕捉到这一点,因为首先检查了 | l &lt; 1 = .. 案例。你可以切换他们的顺序。 (然后它会失败,因为您尝试获取空列表的头部,因此您必须为 createInt [] _ = "" 添加基本情况)
  • 我知道您可能是 Haskell 的新手,但请考虑阅读style guide。这不是好的代码。
  • @AJFarmar 我认为当您学习一门具有许多新概念的新语言并为自己的教育编写程序时,担心这根本不是正确的事情。样式指南对于需要维护的程序很重要。

标签: haskell


【解决方案1】:

我认为您使用的算法不正确,并且您将其变得比需要的复杂。

而且列表不完整,我添加了 90 和 900 个案例。

看看这段代码..我认为它很简单,你会很容易得到它。

import qualified Data.Map as M

    mapInttoRoman:: M.Map Int String
    mapInttoRoman = M.fromList
              [(1,"I"),(4,"IV"),(5,"V"),(9,"IX"),(10,"X"),(40,"XL")
              ,(50,"L"),(90,"XC"),(100,"C"),(400,"CD"),(500,"D"),(900,"CM"),(1000,"M")]

    intToRoman :: Int -> String
    intToRoman 0 = ""
    intToRoman n | M.member n mapInttoRoman = mapInttoRoman M.! n
                 | otherwise = val ++ intToRoman (n-key) 
                 where
                    keys = reverse (M.keys mapInttoRoman)
                    key  = maxValidKey n keys
                    val  = mapInttoRoman M.! key
                    maxValidKey n (k:ks) 
                      | n >= k = k
                      | otherwise = maxValidKey n ks 

测试:

【讨论】:

    猜你喜欢
    • 2019-01-05
    • 2011-04-15
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多