理解 Haskell (<-) 语法糖

tes*_*n3r -1 monads haskell do-notation

我正在尝试使用 Cassava 解析 CSV 文件。我想要一个函数,Nothing如果解析不成功Just (V.Vector (String, String, String))则返回,否则返回。

我正在使用下面的代码:

  {-# LANGUAGE ScopedTypeVariables #-}
module Lib
    ( someFunc
    ) where

import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V

type Dataset = (String, String, String)
someFunc :: Maybe (V.Vector Dataset)
someFunc = do
    csvData <- BL.readFile "TAEE3.SA.csv"
    case decode HasHeader csvData :: Either String (V.Vector (String, String, String)) of
      Left a -> Nothing
      Right v -> Just v
Run Code Online (Sandbox Code Playgroud)

错误是:

  • Couldn't match type ‘IO’ with ‘Maybe’
      Expected type: Maybe BL.ByteString
        Actual type: IO BL.ByteString
    • In a stmt of a 'do' block: csvData <- BL.readFile "TAEE3.SA.csv"
      In the expression:
        do csvData <- BL.readFile "TAEE3.SA.csv"
           case  decode HasHeader csvData ::
                   Either String (V.Vector (String, String, String))
           of
             Left a -> Nothing
             Right v -> Just v
      In an equation for ‘someFunc’:
          someFunc
            = do csvData <- BL.readFile "TAEE3.SA.csv"
                 case  decode HasHeader csvData ::
                         Either String (V.Vector (String, String, String))
                 of
                   Left a -> Nothing
                   Right v -> Just v
   |
14 |     csvData <- BL.readFile "TAEE3.SA.csv"
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^

Run Code Online (Sandbox Code Playgroud)

就像这个<-功能根本不起作用一样。不是应该返回一个ain IO amonad 吗?

Jos*_*ica 8

虽然<-确实给了你ain IO a,但它不会通过将它从 IO monad 中取出来实现。一般来说,不可能从 monad 中取出一个值。它实际上所做的是将do块的其余部分也放入monad 中。为了解决这个问题,您需要让您的函数在 中返回其结果IO,然后添加 areturn将您的最终结果包装MaybeIO

  {-# LANGUAGE ScopedTypeVariables #-}
module Lib
    ( someFunc
    ) where

import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V

type Dataset = (String, String, String)
someFunc :: IO (Maybe (V.Vector Dataset))
someFunc = do
    csvData <- BL.readFile "TAEE3.SA.csv"
    return $ case decode HasHeader csvData :: Either String (V.Vector (String, String, String)) of
      Left a -> Nothing
      Right v -> Just v
Run Code Online (Sandbox Code Playgroud)