2

我在使用 monad-list 构建函数时遇到问题

 > multab 4
 ["1*1=1","1*2=2","1*3=3","1*4=4","2*2=4","2*3=6","2*4=8","3*3=9","3*4=12","4*4=16"]

所以我想开始:

multab :: Integer -> [String]

剩下的,你有什么建议吗?

提前致谢。

4

4 回答 4

8

基本上你想生成一个条目列表,然后打印它们。

让我们从条目开始。这些由两个整数及其乘积组成。所以让我们定义一个类型同义词来保存两个整数

type Entry = (Integer, Integer)

以及计算这些整数乘积的评估函数,

eval :: Entry -> Integer
eval = uncurry (*)

然后,我们定义一个生成条目的函数:

gen :: Integer -> [Entry]
gen n = [(i, j) | i <- [1 .. n], j <- [i .. n]]

例如:

> gen 4
[(1,1),(1,2),(1,3),(1,4),(2,2),(2,3),(2,4),(3,3),(3,4),(4,4)]

接下来,我们需要能够打印一个条目:

showEntry :: Entry -> String
showEntry e@(i, j) = show   i ++ "*"    ++ show j ++ "=" ++ show (eval  e)

例如:

> showEntry (2, 3)
"2*3=6"

最后,让我们将这些部分粘合在一起:

multab :: Integer -> [String]
multab = map showEntry . gen

开始了:

> multab 4
["1*1=1","1*2=2","1*3=3","1*4=4","2*2=4","2*3=6","2*4=8","3*3=9","3*4=12","4*4=16"]
于 2012-07-11T07:53:13.557 回答
2

这是一些基于 Karolis 答案的临时解决方案。

> let nonDec xs = and $ zipWith (>=) (drop 1 xs) xs
nonDec :: Ord b => [b] -> Bool

> let getSets s n = filter nonDec $ replicateM n s
getSets :: Ord b => [b] -> Int -> [[b]]

> getSets [1,2,3,4] 2
[[1,1],[1,2],[1,3],[1,4],[2,2],[2,3],[2,4],[3,3],[3,4],[4,4]]

> let showExp = \[i,j] -> show i ++ "*" ++ show j ++ "=" ++ show (i*j)
showExp :: [Integer] -> [Char]

> map showExp $ getSets [1,2,3,4] 2
["1*1=1","1*2=2","1*3=3","1*4=4","2*2=4","2*3=6","2*4=8","3*3=9","3*4=12","4*4=16"]

所以,multab\n -> map showExp $ getSets [1..n] 2

于 2012-07-11T07:36:46.747 回答
2

执行此操作的自然方法是生成一个包含 or 的所有对的列表,(i, j)然后i <对其= j进行映射(\(i, j) -> show i ++ "*" ++ show j ++ "=" ++ show (i*j))。生成此类列表的最明显方法是编写[(i, j) | i <- [1..n], j <- [1..n], i <= j]. 尽管这样做可能会更好,[1..n] >>= list where list i = map (\k -> (i, k)) [i..n]因为这不会进行任何过滤(因为它不会生成不需要的对)。

于 2012-07-11T07:09:05.240 回答
1

就像使用 List 作为 Monad 的其他答案的替代方案一样。

multab :: Integer -> [String]
multab n = do
    i <- [1..n]
    j <- [i..n]
    return $ show i ++ "*" ++ show j ++ "=" ++ show (i*j)

其中前两个规则将每对整数(i,j)j <= i <= n. 最后一条规则返回打印的值。

更实用的可能是列表理解版本

multab2 :: Integer -> [String]
multab2 n =
    [ show i ++ "*" ++ show j ++ "=" ++ show (i*j)
    | i <- [1..n]
    , j <- [i..n] ]

正如结构所暗示的那样,它可以直接翻译成 monad 版本,尽管这不是最有效的翻译。此外,这等同于从 dblhelix 的答案中内联所有函数时所获得的结果。

于 2012-07-11T14:42:42.903 回答