Как заставить оценку в Haskell?

Я относительно новичок в Haskell, и я пытаюсь узнать, как различные действия могут выполняться последовательно, используя нотацию do. В частности, я пишу программу для сравнения алгоритма (функции)

foo :: [String] -> [String]

Для этого я хотел бы написать функцию, как

import System.CPUTime

benchmark :: [String] -> IO Integer
benchmark inputList = do
                         start <- getCPUTime
                         let r = foo inputList
                         end <- getCPUTime
                         return (end - start) -- Possible conversion needed.

Последняя строка может нуждаться в преобразовании (например, в миллисекунды), но это не тема этого вопроса.

Это правильный способ измерить время, необходимое для вычисления функции foo для некоторого аргумента inputList?

Другими словами, будет ли выражение foo inputList быть полностью уменьшенным перед действием end <- getCPUTime выполняется? Или будет r быть привязанным только к толпе foo inputList?

В общем, как я могу убедиться, что выражение полностью вычислено перед выполнением какого-либо действия?


Этот вопрос был задан несколько месяцев назад программистам (см. Здесь) и на него был принят ответ, но он был закрыт как не по теме, поскольку он относится к переполнению стека. Вопрос не может быть перенесен в переполнение стека, поскольку он старше 60 дней. Итак, по согласованию с модераторами, я размещаю здесь вопрос и публикую принятый вопрос самостоятельно, потому что считаю, что он содержит некоторую полезную информацию.

2 ответа

Ответ, изначально предоставленный пользователем David Lenihan программистам:

Действительно, ваша версия не будет тестировать ваш алгоритм. Как r не используется, он не будет оцениваться вообще.

Вы должны быть в состоянии сделать это с DeepSeq:

benchmark :: [String] -> IO Integer
benchmark inputList = do
                     start <- getCPUTime
                     let r = foo inputList
                     end <- r `deepseq` getCPUTime
                     return (end - start)

(a `deepseq` b) - это какое-то "волшебное" выражение, которое вызывает полную / рекурсивную оценку a перед возвращением b,

Я хотел бы использовать расширение языка -XBangPatterns, я нахожу это довольно выразительным в таких ситуациях. Так что вы бы сказалиlet !r = foo inputList" как в:

{-# LANGUAGE BangPatterns #-}
import System.CPUTime

benchmark :: [String] -> IO Integer
benchmark inputList = do
                         start <- getCPUTime
                         let !r = foo inputList
                         end <- getCPUTime
                         return (end - start)
Другие вопросы по тегам