Я думаю, что вам не хватает расширения .exe. Ваш путь должен быть таким
System.setProperty("webdriver.gecko.driver",
"/usr/local/bin/geckodriver.exe");
Это декларация строгости. В основном это означает, что при создании значения структуры данных она должна быть оценена так называемой «слабой нормальной формой головы». Давайте посмотрим на пример, чтобы мы могли видеть, что это значит:
data Foo = Foo Int Int !Int !(Maybe Int)
f = Foo (2+2) (3+3) (4+4) (Just (5+5))
Функция f
выше, когда оценивается, вернет «thunk»: то есть код для выполнения чтобы выяснить его ценность. В этот момент Foo еще не существует, просто код.
Но в какой-то момент кто-то может попытаться заглянуть внутрь, возможно, через совпадение с шаблоном:
case f of
Foo 0 _ _ _ -> "first arg is zero"
_ -> "first arge is something else"
Это позволит выполнить достаточно кода, чтобы делать то, что ему нужно, и не более того. Таким образом, он создаст Foo с четырьмя параметрами (потому что вы не можете заглядывать в него без его наличия). Во-первых, поскольку мы тестируем его, нам нужно оценить весь путь до 4
, где мы понимаем, что он не соответствует.
Второе не нужно оценивать, потому что мы «Не проверяйте его. Таким образом, вместо сохранения 6
в этой ячейке памяти мы просто сохраним код для возможной последующей оценки (3+3)
. Это будет 6, только если кто-то посмотрит на это.
Третий параметр, однако, имеет перед ним !
, поэтому строго оценивается: (4+4)
выполняется, а 8
] сохраняется в этой ячейке памяти.
Четвертый параметр также строго оценивается. Но вот здесь это немного сложно: мы оцениваем не полностью, а только к слабой нормальной форме головы. Это означает, что мы выясняем, есть ли это Nothing
или Just
что-то, и сохраняем это, но мы не идем дальше. Это означает, что мы сохраняем не Just 10
, а на самом деле Just (5+5)
, оставляя трюк внутри неоценимым. Это важно знать, хотя я думаю, что все последствия этого выходят далеко за рамки этого вопроса.
Вы можете аннотировать аргументы функции таким же образом, если вы включите расширение языка BangPatterns
:
f x !y = x*y
f (1+1) (2+2)
вернет thunk (1+1)*4
.
Простым способом увидеть разницу между строгими и нестрогими аргументами конструктора является то, как они ведут себя, когда они не определены. Учитывая
data Foo = Foo Int !Int
first (Foo x _) = x
second (Foo _ y) = y
Поскольку нестрогий аргумент не оценивается second
, то передача в undefined
не вызывает проблемы:
> second (Foo undefined 1)
1
Но строгий аргумент не может быть undefined
, даже если мы не используем значение:
> first (Foo 1 undefined)
*** Exception: Prelude.undefined
Я считаю, что это аннотация строгости.
Haskell - это чистый и ленивый функциональный язык , но иногда накладные расходы на ленивость могут быть слишком много или расточительными. Поэтому, чтобы справиться с этим, вы можете попросить компилятор полностью оценить аргументы функции вместо того, чтобы разыгрывать шумы вокруг.
На этой странице есть дополнительная информация: Производительность / Строгость .