Почему эта цитата F# не работает во время выполнения?

Я пытаюсь понять, почему этот скрипт F # не работает во время выполнения.

#r "nuget: FsToolkit.ErrorHandling, 2.2.0"

open System
open FsToolkit.ErrorHandling

<@@ async {
        return!
          asyncResult {
            return! (Result.Ok true)
          }
} @@>

Ошибка:

$ dotnet fsi ./Quotations.fsx

System.InvalidOperationException: Could not bind function AsyncResultBuilder.Source in type FsToolkit.ErrorHandling.AsyncResultCEExtensions
   at Microsoft.FSharp.Quotations.PatternsModule.fail@1118[a](Type ty, String nm, Unit unitVar0) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1118
   at Microsoft.FSharp.Quotations.PatternsModule.bindModuleFunctionWithCallSiteArgs$cont@1110(Type ty, String nm, Type[] argTypes, Type[] tyArgs, Unit unitVar) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1169
   at Microsoft.FSharp.Quotations.PatternsModule.bindModuleFunctionWithCallSiteArgs(Type ty, String nm, FSharpList`1 argTypes, FSharpList`1 tyArgs) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1105
   at Microsoft.FSharp.Quotations.PatternsModule.u_ModuleDefn@1572-1.Invoke(FSharpList`1 argTypes, FSharpList`1 tyargs) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1576
   at Microsoft.FSharp.Quotations.PatternsModule.u_constSpec@1636.Invoke(FSharpList`1 argTypes, FSharpList`1 tyargs) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1636
   at [email protected](BindingEnv env) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1501
   at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[a,b](FSharpList`1 cons, FSharpFunc`2 f, FSharpList`1 x) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\local.fs:line 239
   at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 x) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\local.fs:line 247
   at [email protected](BindingEnv env) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1493
   at [email protected](BindingEnv env) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\quotations.fs:line 1508
   at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[a,b](FSharpList`1 cons, FSharpFunc`2 f, FSharpList`1 x) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\local.fs:line 239
   at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc`2 mapping, FSharpList`1 x) in F:\workspace\_work\1\s\src\fsharp\FSharp.Core\local.fs:line 247
...

Это проблема с кавычками F #? Или пакет FsToolkit.ErrorHandling?

Объясните, пожалуйста, сообщение об ошибке и почему оно возникает.


person sdgfsdh    schedule 04.05.2021    source источник


Ответы (3)


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

let returnResult =
  asyncResult {
    return! (Result.Ok true)
  }
      
let quotation =
  <@@
    async {
      return! returnResult
    }
  @@>
  
...

Здесь returnResult будет ValueOp внутри ValueWithName, возвращающим returnResult FSharpFunc.

person Vladislav Khapin    schedule 04.05.2021

Я думаю, что короткий ответ представляет собой комбинацию обоих. Вот что мне удалось определить:

  • Компилятор F# преобразует ваше выражение asyncResult в вызов AsyncResultCEExtensions.Source. См. объяснение здесь и исходный код здесь.
  • Существует несколько различных перегрузок метода Source, поэтому механизм цитирования имеет сложную логику, чтобы попытаться выяснить, какую из них выбрать. См. исходный код здесь .
  • К сожалению, механизм кавычек не может определить, какой Source метод имеет в виду компилятор, поэтому он завершается ошибкой с вставленным вами сообщением об ошибке: Could not bind function AsyncResultBuilder.Source in type FsToolkit.ErrorHandling.AsyncResultCEExtensions.

Можно было бы считать это ошибкой в ​​механизме кавычек, поскольку он не смог понять намерения компилятора. Однако я не уверен, гарантирует ли F#, что каждое возможное допустимое выражение можно использовать в кавычках (отсюда и полудружественное сообщение об ошибке, с которым вы столкнулись). Кто-то, у кого больше знаний о компиляторе F# и внутренностях основной библиотеки, может пролить больше света.

person brianberns    schedule 04.05.2021

Это работает для меня (обратите внимание, что я использую return, а не return!. Я предполагаю, что вывод типа требует дополнительной информации, но я не буду исследовать дальше.

<@@ async {
    return!
      asyncResult {
        return (Result.Ok true)
      }
} @@>

Обновить

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

Проблема, похоже, заключается в библиотеке выражений вычислений, использующей комбинацию вещей -

  • Разделение перегрузок компоновщика на отдельные модули
  • Перегрузка исходного элемента (как упоминалось в других ответах)
  • Использование слабо типизированного Result‹bool, _› (все должно быть заполнено)
  • Другие перегруженные элементы Source, которые плохо типизированы, например Source (s:#seq‹_›)
  • Оценка внутри цитаты

Любое изменение в одном из них решает проблему.

person Adam Nathan    schedule 06.05.2021