2016-09-17 7 views
0

Я думаю, что seq трудно понять, потому что он делает первый аргумент WHNF.Почему функция haskell seq делает первый аргумент WHNF?

Если seq делает первый аргумент нормальной форме, это будет легко понять.

В чем преимущество использования WHNF над NF?

Почему комитет haskell выбирает использование WHNF в функции seq?

+2

С вашей предлагаемой версией 'seq' был бы полезен на многих входах. 'seq [1 ..]' никогда не прекратится, например. – amalloy

+1

Возможный дубликат [Haskell: что такое слабая головная нормальная форма?] (Http: // stackoverflow.com/questions/6872898/haskell-what-is-weak-head-normal-form) – ljedrz

+3

Я не знаю, поможет ли это (просто бросив его как кстати), но 'seq' там, чтобы оценить санк. Это не так, чтобы рекурсивно оценивать thunks. Если вы хотите сделать это рекурсивно, вы тоже можете это сделать, что и есть пакет 'deepseq'. – MasterMastic

ответ

0

Во-первых, API Haskell не имеет предпочтения между WHNF и NF: он предоставляет как seq, так и deepseq.

Возможно, ваш вопрос в том, почему WHNF существует вообще? Проще говоря, это наименьшая оценка. Полный расчет будет идти, как это:

  1. невычисленного (преобразователь)
  2. WHNF: первейшая конструктор известный
  3. глубокие оценки
  4. NF: значение полностью рассчитывается

Однако Haskell ленив, он пытается сделать как можно меньше вычислений, чтобы получить окончательный результат. Например, чтобы вычислить длину списка l, Haskell должен знать, l - [] или _ : t. Затем рекурсивно тот же вопрос о t. Поэтому ему нужно только количество конструкторов : перед окончательным конструктором []. Это по определению последовательные WHNF, которые извлекают только самый главный конструктор значения.

Самый главный конструктор - это минимальная информация, которую вы должны знать о значении, чтобы на самом деле что-то сделать с ним, например, выбрав ветку в case of, как в length чуть выше. Это интерес WHNF к НФ.

Обратите внимание, что для простых типов, таких как Int, каждое значение является его собственный конструктор (2, -7, 15, ...), так WHNF = NF для них.

И, наконец, вам редко все обошлось: задача компилятора заключается в том, чтобы выполнить вашу программу как можно быстрее. При оценке foldl (+) 0 [1..100], если вы попытаетесь выяснить, когда список [1..100] закончится в NF, вы будете совершенно неправы. Компилятор преобразует, что сгиб в этом хвостовой рекурсией петли

let sum ret i = 
       if i == 100 then 100 + ret 
       else sum (ret+i) (i+1) in 
    sum 0 1 

что означает, что не оценивает список вообще. К сожалению, есть ситуации, когда компилятор не может знать, что значение всегда будет в NF, когда будет создан конечный результат программы. Тогда это пустая трата времени и ОЗУ, чтобы держать ее неоцененной (формирование thunk имеет стоимость): лучше deepseq это с самого начала. Или ваш компилятор может иметь ошибки производительности, и вы должны помочь ему с seq или deepseq. Профайлер расскажет вам, какие части вашего кода медленны.

+0

Почему кто-то сделал downvote? –

 Смежные вопросы

  • Нет связанных вопросов^_^