我如何从haskell中的函数返回多个值?

时间:2014-07-30 17:19:18

标签: haskell

Hifriends  函数是否可能返回多个值(例如字符串和布尔值)?  如果是,那么我有一个名为concat的函数,它返回一个布尔值和一个字符串,但我不知道如何调用这些函数,因为我想存储它们。我写了一个非常大的代码。所以我无法发布它。enter code here

concat::(String->Int)->(IO Bool->IO String)
concat line i=do
       return True line

你能帮我写一下函数签名以及如何调用这些函数吗?

我需要一个原型

谢谢

2 个答案:

答案 0 :(得分:11)

返回多个值时,必须返回代数数据类型。关于这一点可以说很多,我会给你一些建议。

  1. 如果您的BoolString在某种程度上更相关,而且它们通常会在您的代码中出现,请定义新的代数数据类型:

    data Question = Question Bool String
    

    您也可以使用访问者函数对其进行定义,该函数也会记录数据:

    data Question = Question{ answered :: Bool
                            , text     :: String }
    

    你可以定义一个函数e。 G。用于初始化问题:

    question :: String -> Question
    question str = Question False (str ++ "?")
    

    或(为了改进文档):

    question :: String -> Question
    question str = Question{ answered = False
                           , text     = str ++ "?"}
    

    然后您可以使用数据构造函数处理数据:

    answer :: String -> Question -> Question
    answer answ (Question False str) =
      Question True (str ++ " " ++ answ ++ ".")
    answer _ old = old
    

    或使用访问器功能(两种方法的许多组合都是可能的):

    answer :: String -> Question -> Question
    answer answ qstn
      | answered qstn = qstn
      | otherwise     = qstn{ answered = True
                            , text     = text qstn ++ " " ++ answ ++ "."}
    

    调用函数的示例:

    answer "Yes it is" (question "Is this answer already too long")
    
  2. 如果您不想定义新的数据类型,请使用预定义的单元组。标准库中定义了许多函数,这使得使用元组更容易。但是,不要在任何地方使用元组 - 更大的代码会变得混乱(缺少文档 - 它不清楚元组代表什么数据),由于多态性,类型错误不会那么容易追踪。

    一种方便使用元组的例子:

    squareAndCube :: Int -> (Int, Int)
    squareAndCube x = (square, square*x)
      where square = x*x
    
    sumOfSquareAndCube :: Int -> Int
    sumOfSquareAndCube x = square + cube
      where (square, cube) = squareAndCube x
    

    关于这个简单问题的说法过多,但由于我提到了标准库支持作为元组的主要优点,我将给出最后一个使用Prelude的uncurry函数的例子:

    sumOfSquareAndCube :: Int -> Int
    sumOfSquareAndCube x = uncurry (+) (squareAndCube x)
    

答案 1 :(得分:10)

是的,您可以使用名为元组的haskell结构返回多个值。

这是一个简单的例子

addAndSub :: Int -> Int -> (Int, Int)
addAndSub a b = (a + b, a - b)

然后,您可以使用fst访问元组的第一部分,使用snd访问第二部分。但是最好是模式匹配

use = case addAndSub 2 3 of
  (i, j) -> i + j

let (i,j) = addAndSub 2 3 
in i + j

现在假设您的函数执行了一些IO并获得了StringBool,那么您的函数看起来会模糊不清

magic :: IO (String, Bool)
magic = do
  string <- getString
  bool   <- getBool
  return (string, bool)

如果您使用do块在monad中工作,您还可以使用更漂亮的表单进行模式匹配。

foo = do
 (i, j) <- magic

请注意,此必须位于执行块中。如果您返回的值m a m是一个monad,您可以只使用do块,例如IO