где в Хаскеле пригодится пункт «где» - PullRequest
6 голосов
/ 17 мая 2011

Я нахожу, что довольно редко сталкиваюсь с ситуациями, когда мне нужно использовать предложение where.Тем не менее, я считаю, что я использовал его очень редко в прошлом.Когда используется предложение where (т.е. в каких ситуациях оно используется)?При каких обстоятельствах я должен использовать это?

Ответы [ 6 ]

11 голосов
/ 17 мая 2011

Есть два отличных ответа на этот вопрос, которые также доступны в Haskell Wiki:

http://haskell.org/haskellwiki/Declaration_vs._expression_style http://haskell.org/haskellwiki/Let_vs._Where

Оба используются для создания локальных определений, которые, возможно, используют значения, переданные в область действия их включающей функции, и, безусловно, недоступны вне контекста включающей функции. Они способствуют повторному использованию кода и минимизируют дублирование. Учитывая fix и лямбду, оба могут быть полностью устранены. Обычно я использую предложения where, когда это возможно, и имею тенденцию использовать предложения let только для определений внутри лямбда-выражения или блока case, или в нотации do, при использовании значений, извлеченных с помощью <- в предыдущих строках. В общем, я думаю, что декларативный стиль теперь намного превалирует над стилем выражения в идиоматическом современном коде Haskell.

3 голосов
/ 18 мая 2011

Один конкретный пример, где я нашел это важным - функция, возвращающая рекурсивно определенный массив.

lucas :: (Integral a) => a -> Array a
lucas n = a where
            a = array (0,n) ((0,2):(1,1):[(i,a!!(i-1) + a!!(i-2)) | i<-[1..n])])

Для чисел Лукаса от 1 до n (Фибоначчи было бы слишком очевидно = P)

Важным моментом является то, что без предложения where массив не будет иметь имени изнутри тела функции, и вы не сможете рекурсивно определить.

1 голос
/ 17 мая 2011

Это в основном вопрос стиля. Даже если они не совсем эквивалентны, это не очень часто, что вы должны использовать один или другой. Вместо этого вам решать, и то, что вы думаете, выглядит лучше.

0 голосов
/ 18 мая 2011

Два стилистических преимущества использования where:

  • Оно помещает ценность определяемой вами вещи близко к ее названию (и типу).

    <b>func x = part1 . part2 (something x)</b>
      where part1 = ...
            part2 = ...
    

    вместо

    <b>func x</b> = let part1 =
                 part2 =
             in <b>part1 . part2 (something x)</b>
    
  • Он поощряет написание кода, который можно читать в «газетном стиле», где важная информация появляется на первом месте, а все подробности - на более позднем.Таким образом, вы можете прекратить чтение, когда почувствуете, что вам не нужно знать остальные детали.

    func x = highlevel1 . highlevel2 (x + 42)
      where highlevel1 = medium (...)
            highlevel2 = medium (...)
    
            medium = ...
    

В основном я использую let, когда сами привязки более интереснычем выражение, и они короткие.Например, когда привязка просто соответствует шаблону:

func x = let (MyData y _ _) = something in y

На мой взгляд, это выглядит лучше, чем

func x = y
  where (MyData y _ _) = something
0 голосов
/ 18 мая 2011

По моему опыту, where более читабелен, чем let, потому что он часто читается до жути похоже на английский.Например:

myFun x = aCoefficient * (10 ** anExponent)  
          where aCoefficient = 100 - x  
                anExponent = x - 2  

В английском я бы описал это как «myFun of x - это коэффициент, умноженный на коэффициент (10 к показателю степени), где коэффициент равен 100 минус x, а показатель степени равен x минус2"

0 голосов
/ 17 мая 2011

Мое эмпирическое правило - если вы определяете что-то на верхнем уровне функции, используйте «где». Если вы определяете вспомогательную функцию, которая имеет несколько предложений, обязательно используйте «где». В другом месте, просто выберите один!

...