En el siguiente código de F#, f1 toma un Span como entrada y f2 llama a f1. El compilador da el error indicado cuando el argumento se canaliza en lugar de pasar.
let f1 (span: Span<byte>) = span.Length let f2() = let buf = [|0uy|].AsSpan() buf |> f1 // FS0412 f1 buf // Ok FS0412 A type instantiation involves a byref type. This is not permitted by the rules of Common IL
¿Hay alguna manera de canalizar un Span en una función F #?
Solo para agregar un poco más de color al por qué :
Byrefs y los tipos similares a byref van en contra de la programación funcional primero.
Se requiere que estos tipos tengan toda su vida útil en la pila y vengan con un análisis del compilador que permita que el tiempo de ejecución elide algunas comprobaciones. Eso es genial para el rendimiento.
Cuando una función se hace de primera clase, implica una asignación de montón. Es un objeto con un método Invoke , básicamente. En el compilador de F# hay varias optimizaciones que intentan convertir una función de F# en solo un método estático (y la mayoría de las declaraciones de funciones de F# son así), pero hay muchas circunstancias en las que se emiten como objetos en el montón (algunas se pueden predecir, algunos no se puede). Eso significa varias cosas:
Hay algunos casos en los que esto sería técnicamente posible, pero no hay nada en el código fuente que indique por qué es posible en algunos casos pero no en otros. La razón sería simplemente "porque el compilador necesita emitir esta función como un objeto" y eso es completamente impredecible y no uniforme. Una sugerencia propuesta ayudaría con esto, pero está cerrada a favor de ajustes en el compilador y como esta sugerencia , que se estima que probablemente no sea tan mala desde el punto de vista de la previsibilidad.
Ahora el caso |> es más interesante, al igual que varias otras funciones que se declaran inline . El operador |> se define literalmente para tomar una función de orden superior como parámetro, por lo que, naturalmente, no debería admitirse. Pero debido a que se define como inline , en realidad podría funcionar ya que es solo una optimización. Sin embargo, esto también puede requerir que solo pueda usarlo en el contexto de otras funciones inline . Es posible que no pueda conectarse a ninguna función arbitraria.
Es por eso que esto no es un error, sino un comportamiento por diseño que se considerará seriamente para mejorar, en caso de que se implemente: https://github.com/fsharp/fslang-suggestions/issues/688