Haskell подставляет оператор (:)

SAMLResponse, выполняемый инструментарием php-saml, не следует схеме xsd, поэтому вы видите эту ошибку.

Вы можете попробовать записать SAMLResponse с SAMLTracer, а затем использовать https://www.samltool.com/validate_xml.php , чтобы выяснить причину аннулирования XML

9
задан Casebash 21 March 2010 в 11:13
поделиться

11 ответов

Вы делаете это:

$ let order_list = [Invoice 2345]
$ let order_list = CashOnDelivery : order_list

Здесь важно отметить, что вы не просто добавляете элемент CashOnDelivery к своему первому ] order_list . Вы определяете новую переменную order_list , которая не имеет ничего общего с первой. Это рекурсивное определение, order_list с правой стороны ссылается на order_list , который вы определяете слева, а не тот, который был определен в предыдущей строке. Из-за этой рекурсии вы получаете бесконечный список.

Я подозреваю, что вы действительно хотели сделать что-то вроде этого:

$ let order_list = [Invoice 2345]
$ order_list
[Invoice 2345]
$ let order_list2 = CashOnDelivery : order_list
$ order_list2
[CashOnDelivery, Invoice 2345]
14
ответ дан 4 December 2019 в 07:48
поделиться

Как программист на восстановление ML, я пойман этим все время . Это одна из немногих неприятностей в Haskell, которую вы не можете легко привязать к имени в предложениях let или где . Если вы хотите использовать let или где , вы должны придумать новые имена. В цикле read-eval-print верхнего уровня, если вы хотите связать одно имя за раз, у вас нет другого выбора. Но если вы хотите вложить конструкции, вы можете использовать нотацию do с помощью монады удостоверения личности:

import Control.Monad.Identity

let order_list = runIdentity $ do
       order_list <- return [Invoice 2345]
       order_list <- return $ CashOnDelivery : order_list
       return order_list

Да, этот код подлый - и не стоит этого в этом примере - но если У меня есть длинный список повторных привязок, я мог бы прибегнуть к нему, поэтому я не

6
ответ дан 4 December 2019 в 07:48
поделиться

Код только что созданных минусов указывает на самого себя: определение order_list , использованное во втором let , является определением создано. Используйте другое имя переменной, чтобы полностью обойти проблему рекурсии, и код также будет менее запутанным.

РЕДАКТИРОВАТЬ: После прочтения ответа Джоэля, кажется, я говорю здесь с Лиспом. Ленивая оценка или нет, в любом случае вы создали рекурсивное определение ...

1
ответ дан 4 December 2019 в 07:48
поделиться

Да, вы пытаетесь напечатать бесконечный список, который вы можете создать с ленивой оценкой. Например,

let a = 1 : a

создает бесконечный список единиц, и вы можете взять их столько, сколько захотите, с помощью функции take или при попытке ее распечатать. Обратите внимание, что вы используете один и тот же идентификатор в левой и правой частях уравнения, и он работает: order_list равен CashOnDelivery: order_list, теперь подставляя: order_list = CashOnDelivery: (CashOnDelivery: order_list) = Cash ... и т. Д.

Если вы хотите создать список [Cash ..., Invoice], не используйте такие имена повторно.

2
ответ дан 4 December 2019 в 07:48
поделиться

Ответ на вопрос:

Что мне делать для простого "прикрепить это к концу (или началу, что угодно) этого списка?" Сделать функцию, которая принимает список и BillingInfo в качестве аргументов, а затем возвращает список?

Ах, но уже есть «функция» для добавления элемента в список: это минусы (:) constructor: -)

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

ghci> let first_order_list = [Invoice 2345]
ghci> first_order_list
[Invoice 2345]
ghci> let second_order_list = CashOnDelivery : first_order_list
ghci> second_order_list
[CashOnDelivery, Invoice 2345]

Относительно второе редактирование:

Поскольку вы спрашиваете, как бы вы сделали что-то подобное в реальной программе, я бы сказал:

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

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

main = do
  orderList <- collectBillingInfos
  putStrLn ("You entered these billing infos:\n" ++ show orderList)

collectBillingInfos :: IO [BillingInfo]
collectBillingInfos = loop []
  where
    loop xs = do
      putStrLn "Enter billing info (or quit)"
      line <- getLine
      if line /= "quit"
        then loop (parseBillingInfo line : xs)
        else return xs

parseBillingInfo :: String -> BillingInfo
parseBillingInfo _ = CashOnDelivery -- Don't want to write a parser here

Подведем итоги; функция loop вызывает себя рекурсивно, каждый раз с новым элементом, добавляемым в список. Пока пользователь не введет «quit», он перестанет вызывать себя и вернет окончательный список.


Исходный ответ, относящийся к отложенной оценке:

Как уже говорили другие, это рекурсивное определение, создающее order_list бесконечный список, содержащий только значения CashOnDelivery .

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

main = do
  orderList <- collectBillingInfos
  putStrLn ("You entered these billing infos:\n" ++ show orderList)

collectBillingInfos :: IO [BillingInfo]
collectBillingInfos = loop []
  where
    loop xs = do
      putStrLn "Enter billing info (or quit)"
      line <- getLine
      if line /= "quit"
        then loop (parseBillingInfo line : xs)
        else return xs

parseBillingInfo :: String -> BillingInfo
parseBillingInfo _ = CashOnDelivery -- Don't want to write a parser here

Подведем итоги; функция loop вызывает себя рекурсивно, каждый раз с новым элементом, добавляемым в список. Пока пользователь не введет «quit», он перестанет вызывать себя и вернет окончательный список.


Исходный ответ, относящийся к отложенной оценке:

Как уже говорили другие, это рекурсивное определение, создающее order_list бесконечный список, содержащий только значения CashOnDelivery . функция loop вызывает себя рекурсивно, каждый раз с новым элементом, добавляемым в список. Пока пользователь не введет «quit», он перестанет вызывать себя и вернет окончательный список.


Исходный ответ, относящийся к отложенной оценке:

Как уже говорили другие, это рекурсивное определение, создающее order_list бесконечный список, содержащий только значения CashOnDelivery . функция loop вызывает себя рекурсивно, каждый раз с новым элементом, добавляемым в список. Пока пользователь не введет «quit», он перестанет вызывать себя и вернет окончательный список.


Исходный ответ, относящийся к отложенной оценке:

Как уже говорили другие, это рекурсивное определение, создающее order_list бесконечный список, содержащий только значения CashOnDelivery . Хотя ленивая оценка не является причиной этого, она делает ее полезной.

Из-за ленивой оценки вы можете использовать order_list следующим образом:

ghci> take 3 order_list
[CashOnDelivery, CashOnDelivery, CashOnDelivery]

Если у вас не было ленивой оценки, вызов take завершится сбоем, потому что он сначала попытается оценить order_list (который бесконечен).

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

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

Я думаю, что здесь важна не лень , а сфера действия . Выражение let x = ... вводит новое определение x , которое заменит любое предыдущее определение. Если справа появится x , то определение будет рекурсивным. Кажется, вы ожидали, что использование order_list в правой части

let order_list = CashOnDelivery : order_list

будет ссылаться на первое определение order_list (т. Е. [Invoice 2345] ]). Но выражение let ввело новую область видимости. Вместо этого вы определили бесконечный список элементов CashOnDelivery .

1
ответ дан 4 December 2019 в 07:48
поделиться

X: L означает «Создать список, начинающийся с X, за которым следуют элементы в списке, определенном L».

Затем вы определяете order_list как CashOnDelivery, за которым следуют элементы в список определен Это определение является рекурсивным, поэтому оценка списка продолжает возвращать CashOnDelivery. Ваш список содержит бесконечное количество значений CashOnDelivery , за которыми следует одно значение Invoice.

0
ответ дан 4 December 2019 в 07:48
поделиться

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

1
ответ дан 4 December 2019 в 07:48
поделиться

Я думаю, вы имеете в виду «это потому, что в нем используется ленивая оценка»? Ответ - да:

let ol = CashOnDelivery : ol

Это говорит нам о том, что ol содержит элемент CashOnDelivery, а затем результат выражения ol. Это выражение не вычисляется до тех пор, пока не будет необходимо (отсюда: лень). Итак, когда ol напечатан, CashOnDelivery будет напечатан первым. Только тогда будет определен следующий элемент списка, что приведет к бесконечному поведению.

0
ответ дан 4 December 2019 в 07:48
поделиться

order_list в этой строке:

let order_list = [Invoice 2345]

- это переменная, отличная от order_list в этой строке

let order_list = CashOnDelivery : order_list

Вторая строка не меняет значение order_list . Он вводит новую переменную с тем же именем, но другим значением.

order_list в правой части второй строки такой же order_list , как в левой части второй строки ; он не связан с order_list в первой строке. Вы получаете бесконечный список, полный CashOnDelivery --- в этом втором списке нет счетов .

0
ответ дан 4 December 2019 в 07:48
поделиться

В ML val не является рекурсивным. Вы должны указать val rec для рекурсивных значений.

val fin = fn _ => 0
val fin = fn x => fin x + 1
(* the second `fin` is calling the first `fin` *)

val rec inf = fn x => inf x + 1
(* ML must be explicitly told to allow recursion... *)
fun inf' x = inf' x + 1
(* though `fun` is a shortcut to define possibly recursive functions *)

В Haskell все верхние уровни, let и , где привязки являются рекурсивными - нет нерекурсивное связывание.

let inf = \_ -> 0
let inf = \x -> inf x + 1
-- the second `inf` completely shadows the first `inf`

Исключение: в do , <- связывание не является рекурсивным. Однако если вы используете {- # LANGUAGE RecursiveDo # -} и импортируете Control.Monad.Fix , вы получите mdo , в котором < - привязка является рекурсивной.

foo :: Maybe [Int]
foo = do
    x <- return [1]
    x <- return (0 : x)  -- rhs `x` refers to previous `x`
    return x
-- foo == Just [0, 1]

bar :: Maybe [Int]
bar = mdo
    y <- return (0 : y)  -- rhs `x` refers to lhs `x`
    return y
-- bar == Just [0, 0, 0, ...]
0
ответ дан 4 December 2019 в 07:48
поделиться
Другие вопросы по тегам:

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