2016-01-06 4 views
1

Я проходил через это blog. Когда я попробовал функцию записи Карри на собственном методе:синтаксис функции карри в swift


func stdCurry(f : (A,B) -> C) -> (A)->(B->C) { 
    return { (a:A) ->(B -> C) in { 
      (b:B) -> C in 
      { 
       return f(a,b) 
      } 

     } 

    } 
} 

я получил ошибку:

:7:22: error: declared closure result 'C' is incompatible with contextual type '_' (b:B) -> C in ^ _

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

+1

это потому, что вы пытаетесь ввести еще один блок этих посторонних скобками цветка после «(Ь: в -> с в» на самом деле вы хотите в этом случае только 2 крышки вложенной, если ввести эти цветистые фигурные скобки , вы закончите с 3 закрытием, а не 2. – Shripada

ответ

2

Внутренние фигурные скобки -> in { ... } быстро сообщает, что эта внутренняя часть является замыканием, тогда как на самом деле она содержит только значение (C тип оценки f(a,b)). Если вы удалите эти внутренние фигурные скобки, ваш пример будет работать.

Например, попробуйте

func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B -> C) { 
    return { (a:A) -> (B -> C) in { 
     (b:B) -> C in 
     return f(a,b) // <-- this is not a closure (just returns a value of type C` 
     } 
    } 
} 

Обратите внимание, что я добавил общие типы, функции подписи выше (возможно, вы действуете является частью класса, и вы получите ваши типы A, B и C оттуда) ,

Чтобы сделать выше более ясной ошибки, рассмотрим это немного более простой пример (принимая закрытие и возвращение его):

/* This is ok */ 
func myClosure<A,B>(f: (A) -> B) -> (A) -> B { 
    return { 
    x in f(x) 
    } 
} 

/* Error: return type here is not (A) -> B, but contains 
    an anonymous closure() -> B */ 
func myClosure<A,B>(f: (A) -> B) -> (A) -> B { 
    return { 
     x in { f (x) } 
    } 
} 

/* Ok */ 
func myClosure<A,B>(f: (A) -> B) -> (A) -> (() -> B) { 
    return { 
     x in { f(x) } 
    } 
} 

Также отметим, что поскольку Swift знает (выводит) --- из ваша подпись функции --- типы, а также то, что тип/закрытие ожидать взамен на каждый статус in ..., вы можете опустить тип закрытия ((a:A) -> (B -> C)), а также ключевое слово return и сделать ваше выражение более компактным следующим образом:

func stdCurry<A, B, C>(f: (A, B) -> C) -> A -> (B -> C) { 
    return { a in { b in f(a, b) } } 
} 

По вашему желанию в комментариях ниже: Вы можете использовать «нескольких операторов» в хвосте, например, используя подход третьего «простого примера» выше, например:

func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B) ->() -> C { 
    return { (a:A) -> (B ->() -> C) in { 
     (b:B) ->() -> C in 
     return { 
      // ... 
      f(a,b) 
     } 
     } 
    } 
} 

Обратите внимание, что, как функция подпись растет несколько «грязной», это выгодно опустить эти детали в реальном закрытии вашей функции, а именно:

func stdCurry<A,B,C>(f : (A,B) -> C) -> (A) -> (B) ->() -> C { 
    return { a in { 
     b in 
     return { 
      // ... 
      f(a,b) 
     } 
     } 
    } 
} 
+0

Спасибо, еще один запрос. Если в хвосте есть несколько инструкций, что мне делать? – Raviprakash

+0

@Ravi Пракаш Счастлив помочь. Вы могли бы использовать анонимное закрытие в обратном типе ('() -> B'), см. Третий« простой пример »в моем редактировании выше. – dfri

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