【问题标题】:Haskell: Using multiple let and return a value after the do block inside a functionHaskell:在函数内的do块之后使用多个let并返回一个值
【发布时间】:2019-12-19 07:26:46
【问题描述】:

正如标题所说,我想在 do 块之后返回一个值。

示例:编写一个在数组中给定位置插入变量的函数:

insertAt :: a -> Int -> [a] -> [a]
insertAt x n xs = do
            let before = take n xs
            let after  = drop n xs
            let merged = before ++ [x] ++ after
            in  merged

例如:

insertAt 'x' 3 "Aleander" => "亚历山大"

无论如何,当使用单个 let 调用时,可以使用 in 关键字返回一个值,但需要多次调用 let如示例中所示,我收到错误:

错误:输入“in”时解析错误

我知道我可以在一次 let 使用中完成所有操作,但我想知道如何处理多次 let 调用 :)

感谢您的帮助!

【问题讨论】:

  • 你根本不需要在这里使用do
  • 不要在此处使用dodo 表达式是带有绑定函数的表达式的语法糖。
  • 不做我会得到一个错误:输入`let'时解析错误
  • @MuradAlm.: 请不要使用 Voodoo 编程 techopedia.com/definition/22860/voodoo-programming :)
  • @MuradAlm:这不是故意的,如果是这样的话,对不起。可能我解释了“without do i will get an error: parse error on input let”有点错误(如“我没有错误,所以我添加了do ).问题说明你很努力,虽然没有完全成功,但已经非常接近正确的结果了。所以我做了+1。:)

标签: haskell functional-programming let


【解决方案1】:

不要使用do 表达式。 do 表达式是带有绑定的表达式的语法糖。是的,列表是Monad 的一个实例,但您使用它的方式不正确。

您可以在这里定义您的lets,如下所示:

insertAt :: a -> Int -> [a] -> [a]
insertAt x n xs =
    let before = take n xs
        after = drop n xs
        merged = before ++ [x] ++ after
    in  merged

但使用splitAt :: Int -> [a] -> ([a], [a]) 可能更优雅,例如:

insertAt :: a -> Int -> [a] -> [a]
insertAt x n xs = let (hs,ts) = splitAt n xs in hs ++ x : ts

【讨论】:

    【解决方案2】:

    如果你想使用 list monad,你可以写

    insertAt x n ys = do
       (i, y) <- zip [0..] ys
       if i == n then [x, y] else [y]
    

    这是通过“编号”输入列表的每个元素来实现的。通常,您只需返回找到的每个元素(请记住,列表 monad 中的 return x == [x])。但是在n 位置,您想在现有列表的当前元素之前“潜入”x。您可以通过提供列表 [x,y] 而不是简单的 [y] 来做到这一点。

    insertAt 'x' 3 "Aleander" 本质上变成了concat ["A", "l", "e", "xa", "n", "d", "e", "r"]


    缺点:无论您提供什么n,它都不会将'x' 附加到输出中,因此这可能更像是列表单子的演示,而不是您实际问题的解决方案。一个简单的解决方法是针对特殊情况 n == 0,然后在 n 元素之后插入 x 。这让你可以追加n == length ys,但不能追加n &gt; length ys

    insertAt x n ys = if n == 0 then x:ys else do
        (i, y) <- zip [1..] ys  -- Note the increase in indices
        if i == n then [y, x] else [y]
    

    【讨论】:

    • 哇!我没有那样想!多谢!我喜欢这样一个事实,即我能够在 Haskell 中用 3 行代码来做事,而在 Java 中需要 30 行(例如)!
    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 2022-07-04
    • 2016-07-31
    • 2020-12-10
    • 2014-09-22
    • 1970-01-01
    • 2016-06-02
    • 2020-05-04
    相关资源
    最近更新 更多