Многократная эффективность в Haskell - PullRequest
4 голосов
/ 16 августа 2011

Это эффективно для проверки нескольких операторов в Haskell? Или это там лучше?

case ((x > -10) && (x < 20),x /= 9,(x `mod` 2) == 0,x) of 
    (False,_,_,_) -> error "Not in range"
    (_,False,_,_) -> error "Must not be 9"
    (_,_,False,_) -> error "Must be even"
    (True,True,True,10) -> stuff ()
    (True,True,True,20) -> stuff ()
    _ -> error "Error Message"

Ответы [ 3 ]

7 голосов
/ 16 августа 2011

Иногда трудно придумать небольшие примеры этой проблемы, которые не выглядят надуманными, но они случаются.Иногда вам нужна куча вычисленных результатов, чтобы выяснить, как разбить функцию на ее случаи.

Так что да, я часто нахожу, что наиболее чистым является использование case в кортеже вещей, которые мне нужныо построении сложных процессов принятия решений.Я доверяю лени вычислять минимум, необходимый для определения того, какую ветвь вызывать.

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

1 голос
/ 17 августа 2011

Предполагая, что забота об эффективности действительно важна и не является преждевременной оптимизацией, вам следует оптимизировать ее для наиболее распространенного случая;Я думаю, что даже в Haskell это означает, что вы хотите, чтобы True,True,True были наверху.

На самом деле, в данном случае, если x == 10 или x == 20 вам не нужно делатьдругие тесты - вам даже не нужно создавать их;и компилятор не может знать (без оптимизации по профилю), какой путь к коду будет выполняться чаще всего, в то время как у вас должна быть разумная догадка (в общем, вам нужно профилирование, чтобы проверить это).

Так чтовы хотите что-то вроде следующего (не проверено):

case x of
  10 -> stuff ()
  20 -> stuff ()
  _ -> case ((x > -10) && (x < 20),x /= 9,(x `mod` 2) == 0) of 
    (False,_,_) -> error "Not in range"
    (_,False,_) -> error "Must not be 9"
    (_,_,False) -> error "Must be even"
    _ -> error "Error Message"

Отказ от ответственности: я не проверял, что происходит с этим кодом и с исходным после всех оптимизаций.

0 голосов
/ 21 августа 2011

Как это?Вы проверяете условия по порядку и возвращаете что-то в первый раз, если не удалось, поэтому внесите условия в список и выполните поиск по нему.

fn x = case lookup False conds of
  Just ohno -> error ohno
  Nothing
    | x == 10 -> stuff
    | x == 20 -> stuff
    | otherwise -> error "Error Message"
 where
  conds = [
    (x > -10 && x < 20, "Not in range"),
    (x /= 9, "Must not be 9"),
    (even x, "Must be even")]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...