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

rah*_*hul 16 haskell

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

concat::(String->Int)->(IO Bool->IO String)
concat line i=do
       return True line
Run Code Online (Sandbox Code Playgroud)

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

我需要一个原型

谢谢

pal*_*lly 11

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

  1. 如果你BoolString他们在某种程度上更相关,他们将经常在你的代码中,定义一个新的代数数据类型:

    data Question = Question Bool String
    
    Run Code Online (Sandbox Code Playgroud)

    您也可以使用访问者函数定义它,该函数也记录数据:

    data Question = Question{ answered :: Bool
                            , text     :: String }
    
    Run Code Online (Sandbox Code Playgroud)

    你可以定义一个函数,例如初始化问题:

    question :: String -> Question
    question str = Question False (str ++ "?")
    
    Run Code Online (Sandbox Code Playgroud)

    或(用于改进文件):

    question :: String -> Question
    question str = Question{ answered = False
                           , text     = str ++ "?"}
    
    Run Code Online (Sandbox Code Playgroud)

    那么你可以使用数据构造函数处理你的数据:

    answer :: String -> Question -> Question
    answer answ (Question False str) =
      Question True (str ++ " " ++ answ ++ ".")
    answer _ old = old
    
    Run Code Online (Sandbox Code Playgroud)

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

    answer :: String -> Question -> Question
    answer answ qstn
      | answered qstn = qstn
      | otherwise     = qstn{ answered = True
                            , text     = text qstn ++ " " ++ answ ++ "."}
    
    Run Code Online (Sandbox Code Playgroud)

    调用函数的示例:

    answer "Yes it is" (question "Is this answer already too long")
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

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

    sumOfSquareAndCube :: Int -> Int
    sumOfSquareAndCube x = uncurry (+) (squareAndCube x)
    
    Run Code Online (Sandbox Code Playgroud)


Dan*_*zer 10

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

这是一个简单的例子

addAndSub :: Int -> Int -> (Int, Int)
addAndSub a b = (a + b, a - b)
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用fst和第二部分访问元组的第一部分snd.然而,模式匹配更可取

use = case addAndSub 2 3 of
  (i, j) -> i + j
Run Code Online (Sandbox Code Playgroud)

要么

let (i,j) = addAndSub 2 3 
in i + j
Run Code Online (Sandbox Code Playgroud)

现在让我们假设你的函数做了一些IO并得到了一个String和一个Bool,你的函数看起来就像是模糊不清

magic :: IO (String, Bool)
magic = do
  string <- getString
  bool   <- getBool
  return (string, bool)
Run Code Online (Sandbox Code Playgroud)

如果你在monad中使用和使用do块,你也可以使用更漂亮的形式进行模式匹配.

foo = do
 (i, j) <- magic
Run Code Online (Sandbox Code Playgroud)

请注意,这必须在do块中.如果您使用的类型返回一个值,你只能使用一个DO块m a,其中m一个单子一样IO.