Haskell слишком многие, где пункты, любые альтернативные предложения

@alanw123: p4pr близко к тому, что я ищу, но он не пересекает границы ответвления:

last if $type eq 'branch';

, Который был основной проблемой, которую я имел, когда я пытался писать свою собственную утилиту - Вы не можете (легко) сказать, как строки отображаются назад на файл, который перешелся от.

11
задан dinsim 22 November 2009 в 18:40
поделиться

7 ответов

Попробуйте написать абстрактные многоразовые функции Вы сможете составить их намного проще

isUnique :: Eq a => [a] -> Bool
isUnique [] = True
isUnique (x:xs) = all (/= x) xs && isUnique xs

noDups :: Eq a => [[a]] -> Bool
noDups = all isUnique
24
ответ дан 3 December 2019 в 01:24
поделиться

Второе предложение where не требуется. вы можете поместить несколько функций в одно и то же предложение where . Все имена функций в одном предложении where входят в область видимости тел этих функций. Подумайте, как работают функции верхнего уровня. Таким образом, вы можете написать:

noDups :: [[a]] -> Bool
noDups du = and (checkSu du)
   where checkDup []     = []
         checkDup (x:xs) = checkRow x ++ checkDup xs

         checkRow []     = [] 
         checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs

На самом деле это намного яснее, потому что в вашей версии, когда вы привязываете x в checkDup , то x все еще находится в область видимости в предложении second where , но вы привязываете аргументы checkRow к тому же имени. Я думаю, что это, вероятно, заставит GHC жаловаться, и это определенно сбивает с толку.

6
ответ дан 3 December 2019 в 01:24
поделиться

Leaving aside some of the details of your particular example (the names are not expecially well chosen), I'm a big fan of where clauses:

  • A function defined in a where clause can be better than a top-level function because a reader knows that the scope of the function is limited---it can be used in just a few places.

  • A function defined in a where clause can capture parameters of an enclosing function, which often makes it easier to read

In your particular example, you don't need to nest the where clauses---a single where clause will do, because functions defined in the same where clause are all mutually recursive with one another. There are other things about the code that could be improved, but with the single where clause I like the large-scale structure fine.

N.B. It is not necessary to indent the where clauses as deeply as you are doing.

4
ответ дан 3 December 2019 в 01:24
поделиться

Haskell позволяет вам ссылаться на вещи, определенные в предложении where, из предложения where (то же самое, что и связывание let). Фактически, предложение where является просто синтаксическим сахаром для связывания let, которое, среди прочего, допускает множественные определения и взаимные ссылки.

пример в порядке.

noDups :: [[a]] -> Bool
noDups du = and (checkDup du)
    where
       checkDup []     = []
       checkDup (x:xs) = checkRow x ++ checkDup xs
           where
               checkRow []     = [] 
               checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs

становится

noDups :: [[a]] -> Bool
noDups du = and (checkDup du)
    where
        checkDup []     = []
        checkDup (x:xs) = checkRow x ++ checkDup xs
        --checkDup can refer to checkRow
        checkRow []     = [] 
        checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs

становится

noDups :: [[a]] -> Bool
noDups du = 
    let checkDup []     = []
        checkDup (x:xs) = checkRow x ++ checkDup xs
        --checkDup can refer to checkRow
        checkRow []     = [] 
        checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs

    in  and (checkDup du)
1
ответ дан 3 December 2019 в 01:24
поделиться
noDups :: [[a]] -> Bool
noDups = and . checkDup
  where
    --checkDup
    checkDup []     = []
    checkDup (x:xs) = checkRow x ++ checkDup xs
    --alternatively
    checkDup xs = concat $ map checkRow xs
    --alternatively
    checkDup = concat . map checkRow
    --alternatively
    checkDup = concatMap checkRow
    --checkRow
    checkRow []     = [] 
    checkRow (x:xs) = [x /= y | y <- xs] ++ checkRow xs
3
ответ дан 3 December 2019 в 01:24
поделиться

Хотя есть исключения, в общем случае вы можете определить «положительные» функции, т.е. в этом случае определить функцию, которая возвращает True , если аргумент делает содержат повторяющиеся данные. Вы можете написать это так:

has_nested_duplicate :: (Eq a) => [[a]] -> Bool
has_nested_duplicate = any has_duplicate
  where
    has_duplicate []     = False
    has_duplicate (x:xs) = x `elem` xs || has_duplicate xs

Здесь используется сопоставление с образцом, any , elem и (||) . Чтобы получить отрицание, используйте , а не :

noDups :: (Eq a) => [[a]] -> Bool
noDups = not . has_nested_duplicate
2
ответ дан 3 December 2019 в 01:24
поделиться

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

Я думаю, вы можете провести четкое различие. Некоторые функции являются основными для модуля, они вносят вклад непосредственно в api. Есть также функции, которые, когда они появляются в документации модуля, заставляют читателя задаться вопросом, какое отношение эта конкретная функция имеет к назначению модуля. Очевидно, что это вспомогательная функция.

Я бы сказал, что такая вспомогательная функция должна быть подчиненной вызывающей функции. Если эта вспомогательная функция должна быть повторно использована в модуле, отделите эту вспомогательную функцию от вызывающей функции, сделав ее прямой доступной функцией модуля. Однако вы, скорее всего, не будете экспортировать эту функцию в определение модуля.
Назовем это рефакторингом в стиле FP.

Жалко, что не существует книги по функциональному программированию, подобной «полному коду». Я думаю, причина в том, что в отрасли слишком мало практики. Но давайте соберем мудрость о stackoverflow: D

1
ответ дан 3 December 2019 в 01:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: