如何从(String,())制作(String,Int)?

时间:2019-01-25 11:10:04

标签: haskell monads

要在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,())的正确结果

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

2 个答案:

答案 0 :(得分:1)

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

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

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

(通常,它是多态的:return :: a -> (String, a)

答案 1 :(得分:0)

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

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

因此,zip函数从两个列表中创建元组列表,然后使用head函数将第一个元素提取为元组,而fst函数则从(字符串,())对。