Понимание Haskell (<-) syntacti c сахара - PullRequest
0 голосов
/ 12 апреля 2020

Я пытаюсь проанализировать файл 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

Ошибка:

  • 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"
   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^

Это похоже на то, что функция <- вообще не работает. Разве он не должен возвращать a в IO a монаде?

1 Ответ

8 голосов
/ 12 апреля 2020

Хотя <- дает вам a в IO a, он не делает этого, убирая его из монады IO. В общем, невозможно извлечь ценность из монад. Что он на самом деле делает, так это помещает остаток блока do в монаду. Чтобы учесть это, вам нужно заставить вашу функцию возвращать свой результат в IO, а затем добавить return для переноса вашего окончательного Maybe обратно в IO:

  {-# 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
...