我在使用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]
其余的,你想提出任何建议吗?
提前致谢。
答案 0 :(得分: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"]
答案 1 :(得分:2)
执行此操作的自然方法是生成包含(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]
可能更好,因为这不会进行任何过滤(因为它不会生成不需要的对)。
答案 2 :(得分: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
。
答案 3 :(得分: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的答案中内联所有函数时所获得的内容。