相关疑难解决方法(0)

如果SML.NET有仿函数为什么不能F#?

这个问题始于

  1. 我将LC PAULSON 的" ML for the working Programmer "(WorldCat)翻译成F#,它使用仿函数作为例子.
  2. 最终希望翻译使用仿函数的Chris Okasaki的" Purely Functional Data Structures "(WorldCat).
  3. 阅读" 类别类型和结构 - 工作计算机科学家类别理论导论 "(WorldCat),作者:Andrea Asperti和Giuseppe Longo.
  4. 不理解这一切,主要是类别理论.

SML.NET可以做仿函数并使用Microsoft .NET.
*请参阅:SML.NET用户指南第4.8.2节类类型和仿函数?

由于Microsoft .NET的一些限制,我一直看到F#无法做真正的仿函数.
*ML仿函数可以用.NET完全编码(C#/ F#)吗?
*算子的任何解决方法?

那么如果SML.NET可以在.NET上运行仿函数那么为什么F#不能呢?SML.NET做了什么,F#不能做什么?

我越了解来自类别理论的仿函数,我越看到它们的美丽,并希望在F#中拥有它们.

编辑

在追求更好的理解范畴论和函数式编程之间的关系看,这些Q&ACS回答#.

f# ocaml ml sml functor

36
推荐指数
1
解决办法
3197
查看次数

我怎样才能将一个值转换回类型?

通常在F#中编写通用代码时,我会遇到与此类似的情况(我知道这非常低效,仅用于演示目的):

let isPrime n =
    let sq = n |> float |> sqrt |> int
    {2..sq} |> Seq.forall (fun d -> n % d <> 0)
Run Code Online (Sandbox Code Playgroud)

对于许多问题,我可以使用静态解析的类型,并通过内联获得性能提升.

let inline isPrime (n:^a) =
    let two = LanguagePrimitives.GenericOne + LanguagePrimitives.GenericOne
    let sq = n |> float |> sqrt |> int
    {two..sq} |> Seq.forall (fun d -> n % d <> LanguagePrimitives.GenericZero)
Run Code Online (Sandbox Code Playgroud)

由于上限序列是一个浮点数,上面的代码将无法编译.非理性地说,我可以退回到int例如.

但是编译器不允许我使用以下任何一个:

  • let sq = n |> float |> sqrt :> ^a
  • let sq = …

f# static-analysis casting compile-time

10
推荐指数
1
解决办法
265
查看次数

为什么我们不能满足带有类型扩展的F#静态成员约束?

我希望能够使用静态方法从其他库扩展类型以启用泛型算法.以VectorN微软新推出的SIMD友好型固定尺寸类型为例.他们定义Zero,他们定义(+),他们定义(/),但我不能使用Array.average它们,因为他们没有定义DivideByInt,我很乐意:

open System.Numerics
type Vector2f with 
  static member DivideByInt (v:Vector2f) (i:int) = v / Vector2f(single i, single i)
let bigArray : Vector2f[] = readABigFile()
printf "the average is %A" (Array.average bigArray)
Run Code Online (Sandbox Code Playgroud)

但它不会让我编译,抱怨

error FS0001: The type 'Vector2f' does not support the operator 'DivideByInt'
Run Code Online (Sandbox Code Playgroud)

为什么F#编译器中存在此限制?

(编辑:基本上问同样的问题.)

f# generic-constraints

5
推荐指数
1
解决办法
349
查看次数

重载度量​​运算符(*)

我试图重置一个Measure类型的(*)运算符.

我想看到的是:

> let x = 1.0<i> * 1.0<i>;;

val x : float = -1.0
Run Code Online (Sandbox Code Playgroud)

以下定义似乎可以解决问题:

> let inline (*) (v1 : float<i>) (v2 : float<i>) = float(-1) * float(v1) * float(v2);;

val inline ( * ) : float<i> -> float<i> -> float
Run Code Online (Sandbox Code Playgroud)

请注意,此示例中的乘积度量正确地解析为<1>,例如在乘以复数的虚数单位时.如果没有此重载定义,则默认产品将解析为<i ^ 2>.

但上面的重载定义有令人讨厌的副作用:

> let y = 1.0 * 1.0;;

let y = 1.0 * 1.0;;
--------^^^

stdin(11,9): error FS0001: This expression was expected to have type
float<i>    
but here has type
float
Run Code Online (Sandbox Code Playgroud)

显然,我的重载定义隐藏了浮点类型的(*)运算符.

我究竟做错了什么?

f#

4
推荐指数
1
解决办法
231
查看次数

非惯用全局运算符重载如何工作?

我想了解这个答案的代码

type Mult = Mult with
    static member inline ($) (Mult, v1: 'a list) = fun (v2: 'b list) -> 
        v1 |> List.collect (fun x -> v2 |> List.map (fun y -> (x, y))) : list<'a * 'b>
    static member inline ($) (Mult, v1:'a      ) = fun (v2:'a) -> v1 * v2 :'a

let inline (*) v1 v2 = (Mult $ v1) v2
Run Code Online (Sandbox Code Playgroud)

F#可以解决重载成员.(因为它不支持成员的currying).所以,我认为,它也适用于方法

但它没有:

type Mult = Mult with
        static member inline Do (Mult, v1: 'a list) …
Run Code Online (Sandbox Code Playgroud)

f# overloading operator-overloading operators

3
推荐指数
1
解决办法
92
查看次数

F#运算符重载奇怪的行为

让我们说,由于一些奇怪的原因,我希望有这个功能:

let (~-) (str:string) = 42
Run Code Online (Sandbox Code Playgroud)

所以我可以做这样的事情,得到42结果:

-"test"
val it : int = 42
Run Code Online (Sandbox Code Playgroud)

哪个好.但现在我这样做:

let a = 100
-a
Run Code Online (Sandbox Code Playgroud)

我明白了:

error FS0001: This expression was expected to have type
    string    
but here has type
    int    
Run Code Online (Sandbox Code Playgroud)

知道为什么会这样吗?

f#

2
推荐指数
1
解决办法
90
查看次数