Я также сделал это с помощью jQuery. В моем случае я хотел увидеть немного другого меню (10px). Так что это работает без Javascript (но без перехода также).
#menu li ul {
list-style: none;
height: 10px;
overflow: hidden;
margin: 0;
padding: 0;
}
#menu li:hover ul {
height: 100%;
}
Это мой JS:
//Save the height set in css (10px)
var csshoehe = $("ul li ul").height();
// Open all the menus
$("ul li ul").css("height", "100%");
//Save each height in data-attribute
//then shrink it down again
$.each($("ul li ul"), function(){
var hoehe = $(this).height();
$(this).data("hoehe", hoehe);
$(this).css("height", csshoehe);
});
$("ul li").hover(
function(){
var orig = $(this).children("ul").data("hoehe");
$(this).children("ul").stop(true,false).delay(150).animate({"height": orig});
}, function(){
$(this).children("ul").stop(true,false).delay(400).animate({"height": csshoehe});
});
Надеюсь, это кому-нибудь поможет:)
Изначально я собирался опубликовать это в качестве комментария, но решил рассказать немного подробнее.
Строго говоря, get
не «принимает» аргументы . Я думаю, что многое из того, что происходит, замаскировано тем, что вы не видите - определениями экземпляров монады State.
get
на самом деле является методом класса MonadState. Монада State - это экземпляр MonadState, обеспечивающий следующее определение get
:
get = State $ \s -> (s,s)
Другими словами, get
просто возвращает очень простую монаду State (помня, что монада может быть рассматривается как "оболочка" для вычислений), где любой ввод s
в вычисление вернет пару s
в качестве результата.
Следующее, что нам нужно, посмотрите на это >> =
, которое State определяет следующим образом:
m >>= k = State $ \s -> let
(a, s') = runState m s
in runState (k a) s'
Итак, >> =
приведет к новому вычислению, которое не будет вычисляться, пока не получит начальное состояние (это верно для всех вычислений State, когда они ' re в их «завернутом» виде). Результат этого нового вычисления достигается путем применения того, что находится справа от >> =
, к результату выполнения вычисления, которое было слева. (Это довольно запутанное предложение, которое может потребовать дополнительного чтения или двух.)
Я считаю весьма полезным «десахарировать» все, что происходит. Для этого потребуется гораздо больше печатать, но ответ на ваш вопрос (откуда get
]) должен быть очень ясным. Обратите внимание, что следующий код следует рассматривать как псевдокод ...
test x =
State $ \s -> let
(a,s') = runState (State (\s -> (s,s))) s --substituting above defn. of 'get'
in runState (rightSide a) s'
where
rightSide test =
let test' = x ++ test in
State $ \s2 -> let
(a2, s2') = runState (State $ \_ -> ((), test')) s2 -- defn. of 'put'
in runState (rightSide2 a2) s2'
rightSide2 _ =
-- etc...
Это должно сделать очевидным, что конечный результат нашей функции - это новое вычисление Состояния, которому потребуется начальное значение ( s
), чтобы выполнить остальную работу. Вы предоставили s
как "testtest"
с вашим вызовом runState
. Если вы замените «testtest» на s
в приведенном выше псевдокоде, вы увидите, что первое, что произойдет, - это мы запустим get
с «testtest» в качестве «начального состояния». Это дает («testtest», «testtest»)
и т. Д.
Итак, здесь get
получает ваше начальное состояние «testtest». Надеюсь, это поможет!
s
в приведенном выше псевдокоде, вы увидите, что первое, что произойдет, - это мы запустим get
с «testtest» в качестве «начального состояния». Это дает («testtest», «testtest»)
и т. Д.
Итак, здесь get
получает ваше начальное состояние «testtest». Надеюсь, это поможет!
s
в приведенном выше псевдокоде, вы увидите, что первое, что произойдет, - это мы запустим get
с «testtest» в качестве «начального состояния». Это дает («testtest», «testtest»)
и т. Д.
Итак, здесь get
получает ваше начальное состояние «testtest». Надеюсь, это поможет!
Это может помочь вам глубже взглянуть на то, что на самом деле представляет собой конструктор типа State
и как его использует runState. В GHCi:
Prelude Control.Monad.State> :i State
newtype State s a = State {runState :: s -> (a, s)}
Prelude Control.Monad.State> :t runState
runState :: State s a -> s -> (a, s)
State
принимает два аргумента: тип состояния и возвращаемый тип. Он реализован как функция, принимающая начальное состояние и выдающая возвращаемое значение и новое состояние.
runState
принимает такую функцию, начальный ввод, и (наиболее вероятно) просто применяет одну к другой для получения Пара (результат, состояние).
Ваша функция test
представляет собой большую композицию функций типа State
, каждая из которых принимает входное состояние и дает выход (результат, состояние), подключены друг к другу способом, который имеет смысл для вашей программы. Все runState
предоставляет им начальную точку состояния.
В этом контексте get
- это просто функция, которая принимает состояние в качестве входа и возвращает выход (результат, состояние), так что результатом является состояние входа, а состояние не изменяется (состояние выхода - состояние входа) . Другими словами, get s = (s, s)
Просматривая главу 8 («Функциональные синтаксические анализаторы») Грэма Хаттона Programming in Haskell несколько раз, пока я не понял ее должным образом, с последующим переходом к руководству Все о монадах , этот щелчок сделал для меня.
Проблема с монадами заключается в том, что они очень полезны для некоторых вещей, которые те из нас, кто имеет обычный опыт программирования, находят совсем не похожи. Требуется некоторое время, чтобы понять, что поток управления и состояние обработки не только достаточно похожи, чтобы их можно было обрабатывать одним и тем же механизмом, но и являются одним и тем же, когда вы отступаете достаточно далеко.
Прозрение пришло, когда я задумался. управляющие структуры в C ( для
и , в то время как
и т. д.), и я понял, что наиболее распространенной структурой управления было простое размещение одного оператора перед другим. Прошел год изучения Haskell, прежде чем я понял, что это даже структура управления.