【问题标题】:How to make (String,Int) from (String,())?如何从(String,())制作(String,Int)?
【发布时间】:2019-06-19 05:17:20
【问题描述】:

对于 WriterMonads 的练习,我需要创建一个函数来记录它所做的事情。我不能使用元组构造函数 (,)。

我已经有一个结果类型为 (String,()) 的日志函数 现在我需要使用这个,但结果类型为 (String,Int)

但我不知道如何将 (String,()) 元组转换为 (String,Int)

logMsg :: String -> (String,())
logMsg  msg = (msg,()) -- Durch Lösung ersetzen.

logOp :: Int -> Int -> Int -> String -> (String,())
logOp v1 v2 res math = do
    logMsg "The value of "
    logMsg $ show v1
    logMsg  math
    logMsg $ show v2
    logMsg " is "
    logMsg $ show res
    logMsg ".\n"


mult :: Int -> Int -> (String,Int)
mult m1 m2 = logOp m1 m2 (m1*m2) "*"

我测试过

logOp m1 m2 (m1*m2) "*"

执行类型 (String,()) 的正确结果

我不知道,有什么提示吗?

【问题讨论】:

  • 注意表达式if a == c then (a,d):r else (a,b):updRel r c d暗示db必须是同一类型。
  • 哦,好吧。所以那行不通。如果没有元组构造函数(,),我还能如何更改元组的值
  • 是的,对于编辑后的问题,mult 函数的类型应该是mult :: Int -> Int -> (String,()) 而不是(String, Int)。你想把Int 值放在元组的第二个元素中是什么?
  • 类型已给定,无法更改。第二个参数是多重化的结果。不能说为什么,它只是需要在那里。
  • 好吧,Haskell中的变量是不可变的,你不能改变它。构造 (String, Int) 对的唯一方法是创建一个新的。

标签: haskell monads


【解决方案1】:

通常,在处理 monad 时,会使用 monadic 函数 return(>>=)。您已经在 do 块中隐式使用了 (>>=)

对于mult,您可以尝试使用do 并在其中使用return。在这种非常特殊的情况下,您可以假设 return 被定义为

return :: Int -> (String, Int)
return x = ("", x)

(一般情况下是多态的:return :: a -> (String, a)

【讨论】:

    【解决方案2】:

    我找不到不使用构造函数直接更新元组中的值的方法,所以我不得不以低效的方式编写它。但是这个没有使用元组构造函数:

    mult m1 m2 = head $ zip [fst $ logOp m1 m2 (m1*m2) "*"] [m1*m2]
    

    所以zip 函数从两个列表中创建元组列表,然后使用head 函数我们将第一个元素提取为元组,fst 函数从 (String,()) 对中提取字符串.

    【讨论】:

      猜你喜欢
      • 2019-08-12
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-22
      相关资源
      最近更新 更多