2016-03-05 2 views
1
y :: (f->f) -> f 
y f = f (y f) 

indexOf :: Char -> String -> Maybe Int 
indexOf c l = 
    y(\ ff c (h:t) pos -> 
     if (c == h) then Just pos 
      else ff c t (pos + 1) 
     )(c, l, 0) 

indexOf c [] = Nothing 

Это дает мне две ошибки компиляции: Код должен найти позицию char c в строке. Например: IndexOf ('а', 'лампа') = 2Haskell. Рекурсивная Лямбда. Ошибки

Couldn't match expected type `[(Char, String, Integer)] 
            -> Integer -> Maybe Integer' 
       with actual type `Maybe Int' 
    The lambda expression `\ ff c (h : t) pos -> ...' 
    has four arguments, 
    but its type `((Char, String, Integer) -> Maybe Int) 
        -> (Char, String, Integer) -> Maybe Int' 
    has only two 
    In the first argument of `y', namely 
     `(\ ff c (h : t) pos 
      -> if (c == h) then Just pos else ff c t (pos + 1))' 
    In the expression: 
     y (\ ff c (h : t) pos 
      -> if (c == h) then Just pos else ff c t (pos + 1)) 
     (c, l, 0) 


    Couldn't match expected type `[(Char, String, Integer)] 
            -> Integer -> Maybe Integer' 
       with actual type `Maybe Int' 
    The function `ff' is applied to three arguments, 
    but its type `(Char, String, Integer) -> Maybe Int' has only one 
    In the expression: ff c t (pos + 1) 
    In the expression: if (c == h) then Just pos else ff c t (pos + 1) 

Я не знаю, как восстановить его. Пожалуйста, дайте мне руку :)

+1

Функции Haskell называются 'function abc ...' not 'function (a, b, c, ...)'. Структура '(a, b, c, ...)' называется кортежем, но определенная функция не принимает ее. – AJFarmar

ответ

4

проблема здесь заключается в том, что вы смешиваете кортежи и кэрри аргументы (вы должны попытаться остаться с основной формой двух кэрри аргументов, если вы не хотите, чтобы изменить y) - но ваше мышление неплохое!

действительно это лишь несколько небольших изменений, чтобы заставить его работать:

indexOf :: Char -> String -> Maybe Int 
indexOf c ls = 
    y(\ ff (ls, pos) -> 
     case ls of 
     (h:t) 
      | h == c -> Just pos 
      | otherwise -> ff (t, pos+1) 
     [] -> Nothing 
    )(ls, 0) 

, как вы можете видеть, что я сделал:

  • переместил прецедентное раскол внутри
  • переписал аргументы в кортеж rest -list и позиция
  • повторно используется c с закрытием, которое вы получаете бесплатно;)

здесь в действии:

λ> indexOf 'l' "Hello" 
Just 2 
λ> indexOf 'a' "Hello" 
Nothing 

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

indexOf :: Char -> String -> Maybe Int 
indexOf c = indexOf' 0 
    where 
    indexOf' _ [] = Nothing 
    indexOf' pos (h:t) 
     | c == h = Just pos 
     | otherwise = indexOf' (pos+1) t 
+0

Еще раз спасибо. Вы сказали, что я смешиваю карри и кортежи. Я не вижу этого. Если я правильно понимаю: в вашем примере вы использовали currying. Я прав? – Gilgamesz

+2

'y (\ ff c (h: t) pos -> ...) (c, l, 0)' вызывает 'y' с одним аргументом, а не тремя, как вы планируете. '(c, l, 0)' является трехкорневым, помните. – amalloy

+0

@ Gilgamesz Carsten показал, как использовать кортежи как в шаблонах лямбда, так и в аргументах: 'y (\ ff (ls, pos) -> ...) (ls, 0)'. Вы также можете использовать версию в карри, просто удаляя кортежи в обоих местах: 'y (\ ff ls pos -> ...) ls 0'. Оба прекрасны, но смешивание двух подходов приведет к несоответствию типа. – chi

Смежные вопросы