SAMLResponse, выполняемый инструментарием php-saml, не следует схеме xsd, поэтому вы видите эту ошибку.
Вы можете попробовать записать SAMLResponse с SAMLTracer, а затем использовать https://www.samltool.com/validate_xml.php , чтобы выяснить причину аннулирования XML
Вы делаете это:
$ 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]
Как программист на восстановление 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
Да, этот код подлый - и не стоит этого в этом примере - но если У меня есть длинный список повторных привязок, я мог бы прибегнуть к нему, поэтому я не
Код только что созданных минусов указывает на самого себя: определение order_list
, использованное во втором let
, является определением создано. Используйте другое имя переменной, чтобы полностью обойти проблему рекурсии, и код также будет менее запутанным.
РЕДАКТИРОВАТЬ: После прочтения ответа Джоэля, кажется, я говорю здесь с Лиспом. Ленивая оценка или нет, в любом случае вы создали рекурсивное определение ...
Да, вы пытаетесь напечатать бесконечный список, который вы можете создать с ленивой оценкой. Например,
let a = 1 : a
создает бесконечный список единиц, и вы можете взять их столько, сколько захотите, с помощью функции take или при попытке ее распечатать. Обратите внимание, что вы используете один и тот же идентификатор в левой и правой частях уравнения, и он работает: order_list равен CashOnDelivery: order_list, теперь подставляя: order_list = CashOnDelivery: (CashOnDelivery: order_list) = Cash ... и т. Д.
Если вы хотите создать список [Cash ..., Invoice], не используйте такие имена повторно.
Ответ на вопрос:
Что мне делать для простого "прикрепить это к концу (или началу, что угодно) этого списка?" Сделать функцию, которая принимает список и 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
это не совсем полезно, но есть много других мест, где возможность программирования с бесконечными (или просто очень большими) структурами данных очень удобна.
Я думаю, что здесь важна не лень , а сфера действия . Выражение let x = ...
вводит новое определение x
, которое заменит любое предыдущее определение. Если справа появится x
, то определение будет рекурсивным. Кажется, вы ожидали, что использование order_list
в правой части
let order_list = CashOnDelivery : order_list
будет ссылаться на первое определение order_list
(т. Е. [Invoice 2345]
]). Но выражение let
ввело новую область видимости. Вместо этого вы определили бесконечный список элементов CashOnDelivery
.
X: L означает «Создать список, начинающийся с X, за которым следуют элементы в списке, определенном L».
Затем вы определяете order_list как CashOnDelivery, за которым следуют элементы в список определен Это определение является рекурсивным, поэтому оценка списка продолжает возвращать CashOnDelivery. Ваш список содержит бесконечное количество значений CashOnDelivery , за которыми следует одно значение Invoice.
Haskell использует ленивую оценку ... ничего не оценивается до тех пор, пока это не понадобится, именно поэтому order_list хранится как минусы, содержащие CashOnDelivery и другую, неоцененную ячейку, снова ссылающуюся на order_list.
Я думаю, вы имеете в виду «это потому, что в нем используется ленивая оценка»? Ответ - да:
let ol = CashOnDelivery : ol
Это говорит нам о том, что ol содержит элемент CashOnDelivery, а затем результат выражения ol. Это выражение не вычисляется до тех пор, пока не будет необходимо (отсюда: лень). Итак, когда ol напечатан, CashOnDelivery будет напечатан первым. Только тогда будет определен следующий элемент списка, что приведет к бесконечному поведению.
order_list
в этой строке:
let order_list = [Invoice 2345]
- это переменная, отличная от order_list
в этой строке
let order_list = CashOnDelivery : order_list
Вторая строка не меняет значение order_list
. Он вводит новую переменную с тем же именем, но другим значением.
order_list
в правой части второй строки такой же order_list
, как в левой части второй строки ; он не связан с order_list
в первой строке. Вы получаете бесконечный список, полный CashOnDelivery
--- в этом втором списке нет счетов
.
В 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, ...]