IO в где пункт - PullRequest
       24

IO в где пункт

5 голосов
/ 29 марта 2011

Я думал, что начинаю понимать IO в Haskell, пока не столкнулся со следующей проблемой.

У меня есть следующая функция, которая возвращает тип IO Float:

getFundPrice :: Int ->  Int -> IO Float
getFundPrice fund date = do 
                       priceList <- getFundPrice' fund date
                       let h = head priceList
                       return  h

ФункцияgetFundPrice 'использует библиотеку базы данных takusen и возвращает список типа IO [Float].

Я могу успешно протестировать функцию getFundPrice с Hunit, используя следующее:

  p <- getFundPrice 120 20100303
  assertEqual
    "get fund price"
    10.286 
    (p)

Проблема, которая ставит меня в тупик, заключается в следующем определении функции:

lastPos :: Int -> (Shares,Float) -> Period -> Fund -> (Shares,Float)
lastPos endDate begPos [] fund  = (fst begPos, trnPrice) 
                               where trnPrice = do
                                             price <- getFundPrice fund endDate
                                             return price                                                                        

Ошибка, которую я получаю при попытке компиляции: «Не удалось найти ожидаемый тип Float' against inferred type IO Float '»

Я думал, что действие * цена <- getFundPrice *</em> извлечет цену для меня, как это происходит с моим кодом HUnit.

Чем отличается использование в предложении where?

Ответы [ 2 ]

8 голосов
/ 29 марта 2011

Если вы удалите явную подпись типа, вы увидите правильный тип:

lastPos :: Int -> (Shares,Float) -> Period -> Fund -> (Shares,IO Float)

Обратите внимание на IO Float в конце.Вы определили trnPrice как действие ввода-вывода, которое извлекает значение с плавающей запятой.Вы не выполнили это действие, чтобы получить значение!Вы не можете выполнить это действие из любого места, за исключением монады IO, в которой нет lastPos. Что вы можете сделать:

lastPos :: Int -> (Shares,Float) -> Period -> Fund -> IO (Shares, Float)
lastPos endDate begPos [] fund  = do
    price <- getFundPrice fund endDate
    return (fst begPos, price)

, которая поднимает все lastPos в IO.

5 голосов
/ 29 марта 2011

Сущность монады IO в том, что вы никогда не сможете избавиться от нечистой порчи . Поскольку ваша функция getFundPrice не является чистой, ничто из ее вызова также не может быть чистым.

Ваша функция должна иметь тип

lastPos :: Int -> (Shares,Float) -> Period -> Fund -> IO (Shares,Float)

Если это поможет прояснить ситуацию, в вашем предложении where оператор return оборачивает чистую цену обратно в IO. 1 не может этого избежать - монада IO разработана, чтобы не допустить этого.

На самом деле это точно так же, как where trnPrice = getFundPrice fund endDate

1 на самом деле есть бэкдор , но использовать его не очень хорошо

...