-3

在 Haskell 中,带有标题的程序有什么区别

module Main where

import Data.List

module Main where

import Data.Char

///////////////////////////////////////// /

这些是我用来学习的玩具程序:

方案一:

   module Main where

    import Data.Char

    prepets1 = ["cat", "dog", "scorpion", "cobra"]
    prepets2 = ["cat", "dog"]
    prepets3 = ["cat", "scorpion"]
    prepets4 = [prepets2, prepets3]

    data Pet = Pet {name :: String,
            venomous :: Bool,
            cost :: Integer }
        deriving (Eq, Show)

    venomous' :: String -> Bool
    venomous' = (>3). length

    cost' :: String -> Integer
    cost' = sum . map (fromIntegral . ord)

    petify :: String -> Pet
    petify s = Pet s (venomous' s) (cost' s)

    pets1 = map petify prepets1

    pets2 = [Pet s (venomous' s) (cost' s) | s <- prepets1]

    ouch1 :: [String] -> Bool
    --is any string here the name of a venomous pet?
    ouch1 xs = True

    ouch2 :: [[String]] -> Bool
    -- Is any string here the name of a veno,ous pet?
    ouch2 xs = False

    printpets = putStrLn . unlines. map show

    blankline = putStrLn "\n"

    main = do
        blankline
        print $ petify "cat"
        blankline
        print $ petify "scorpion"
        blankline
        printpets pets1
        blankline
        printpets pets2
        blankline
        print $ ouch1 prepets2
        blankline
        print $ ouch1 prepets3

方案二:

module Main where

import Data.List

data Report = Report {recipe :: Recipe,
                      legal  :: Bool,
                      popcnt :: Integer,
                      cost   :: Integer}
              deriving (Eq, Show)

type Recipe = String  -- seven bits to encode seven ingredients

-- recipes in Gray-code order

gray :: Integer -> [Recipe]
gray n
  | n == 0 = [""]
  | n >  0 = map (++"0") (gray (n-1)) ++
             map (++"1") (reverse (gray (n-1)))

recipes = gray 7

-- recipe analysis and report generation

reports = [Report r (legal' r) 6 16 | r <- recipes]  -- fix!

legal_reports = [r | r <- reports, legal r]

legal' :: Recipe -> Bool
legal' r = take 3 r == "000"  -- fix!

ruleset = [rule0, rule1, rule2, rule3, rule4, rule5]

-- Rule 0: If truffles, then precisely truffles.
rule0 r = True  -- fix!

-- Rule 1: Either truffles or some meat.
rule1 r = False -- fix!

-- Rule 2: Not both peppers and onions.
rule2 r = True  -- fix!

-- Rule 3: If bacon, then peppers.
rule3 r = False  -- fix!

-- Rule 4: If sausage, then onions.
rule4 r = True  -- fix!

-- Rule 5: If ham, then mushrooms.
rule5 r = False  -- fix!

popcnt' :: Recipe -> Integer
-- number of ingredients
popcnt' x = 3  -- fix!

type Bit  = Char

type Cost = Integer

cost' :: Recipe -> Cost
cost' x = 42  -- fix!

includeCost :: Cost -> Bit -> Cost
includeCost cost bit = if bit == '1' then cost else 0

costs = [1, 2, 4, 8, 16, 32, 64]

-- ingredient encoding

peppers   r = r!!0 == '1'

bacon     r = r!!1 == '1'

ham       r = r!!2 == '1'

sausage   r = r!!3 == '1'

onions    r = r!!4 == '1'

mushrooms r = r!!5 == '1'

truffles  r = r!!6 == '1'

preciselyTruffles = (== "0000001")

-- main processing

type Run  = [Report]  -- sequence of legal reports that satisfy the metarule

-- Approach A: Work directly with Grey-code order

runsA = extractRunsA reports

extractRunsA :: [Report] -> [Run]
extractRunsA as
  | clean == [] = []

  | otherwise   = r : extractRunsA as'
                    where (r, as') = break illegal clean
                          clean    = dropWhile illegal as
                          illegal  = not . legal

-- Approach B: Guess a starting seed of a long Hamming run

runsB = extractRunsB legal_reports

extractRunsB :: [Report] -> [Run]
extractRunsB [] = []
extractRunsB xs = run : extractRunsB xs'
                    where run = buildRun (head xs) (tail xs)
                          xs' = xs \\ run  -- list difference

buildRun :: Report -> [Report] -> Run
buildRun seed reports
  | endOfRun  = [seed]

  | otherwise = seed : buildRun seed' reports'
                  where endOfRun   = successors == []
                        successors = filter (.~. seed) reports
                        reports'   = reports \\ [seed]
                        seed'      = head successors

(.~.) :: Report -> Report -> Bool
-- test recipe pairs for Hamming distance 1
x .~. y = True -- fix!

-- print routines

printReports :: [Report] -> IO ()
printReports = putStrLn . unlines . map show

printRecipes :: [Report] -> IO ()
printRecipes = putStrLn . showRecipes

printRuns :: [Run] -> IO ()
printRuns = putStrLn . unlines . map showRecipes

printRuns' :: [Run] -> IO ()
printRuns' = putStrLn . unlines . map showRecipes'

showRecipes :: Run -> String
showRecipes = unlines . map showNames

showRecipes' :: Run -> String
showRecipes' run = (unlines . map showNames) run ++ "  total cost  = $" ++
                   show 15 ++ "\n" ++  -- fix!
                   "  prize money = $" ++ show 4 ++ " million\n"  -- fix!

type Name = String

showNames :: Report -> String
showNames r = (concat . addEggs . translate . recipe) r ++
              "  (" ++ show (popcnt r) ++ ")" ++
              "  $" ++ show (cost r)

translate :: Recipe -> [Name]
translate = zipWith includeName names

includeName :: Name -> Bit -> Name
includeName name bit = if bit == '1' then name else replicate (length name) ' '

addEggs :: [Name] -> [Name]
addEggs = id  -- fix!

names =
  ["peppers ", "bacon ", "ham ", "sausage ", "onions ", "mushrooms ", "truffles"]

blankline = putStrLn ""

render = putStrLn . (++ "\n")

main = do
  blankline
  -- render       "All reports:"
  -- printReports reports
  render       "First ten recipes with number of ingredients and cost:"
  printRecipes $ take 10 reports
  render       "All legal recipes with number of ingredients and cost:"
  printRecipes legal_reports
  render       "All Gray-code runs:"
  printRuns    runsA
  render       "All Gray-code runs with total cost and prize money:"
  printRuns'   runsA
  render       "All seed-generated runs:"
  printRuns    runsB
  render       "All seed-generated runs with total cost and prize money:"
  printRuns'   runsB
4

2 回答 2

5

一种允许您使用在Data.List 模块中可以看到的所有功能,另一种允许您使用在Data.Char 模块中定义的所有功能。

读一读。

Data.List充满了非常方便的列表处理功能。Data.List 中的许多函数仍然可用,因为它们在Prelude(隐式导入)中,但有些不是

您不需要import Data.Char使用 Char 类型,它用于额外的功能,主要用于告诉您拥有哪种字符。


您可以通过编辑导入并读取错误来检查他们从 Data.List 或 Data.Char 中使用了哪些函数。

程序 1 使用ord来自 Data.Char(请参阅hoogle以了解它是什么或它是如何工作的)来计算宠物的成本,这似乎取决于其中的字母(而宠物是否有毒取决于有多少个字母有)!

第二个使用\\列表差异(请参阅hoogle以了解它是什么或它是如何工作的)。

于 2013-02-06T22:38:01.663 回答
4

他们正在导入不同的模块(即,将这些模块中定义的所有函数和数据类型带入当前命名空间)。Data.List包含用于处理列表的函数,例如++(append) 和map; Data.Char包含与 Chars 相关的函数,例如isAlphatoUpper

于 2013-02-06T22:37:23.200 回答