我正在尝试将Haskell核心库的Arrows转换为F#(我认为这对于更好地理解Arrows和F#是一个很好的练习,我可能能够在我正在开发的项目中使用它们.)但是,直接翻译由于范式的不同,是不可能的.Haskell使用类型类来表达这些东西,但我不确定F#构造最好用F#的习语映射类型类的功能.我有一些想法,但最好把它提到这里,看看哪些被认为是最接近的功能.
对于tl; dr crowd:我如何将类型类(一个Haskell成语)翻译成F#惯用代码?
对于那些接受我长篇解释的人:
来自Haskell标准库的代码是我正在尝试翻译的一个例子:
class Category cat where
id :: cat a a
comp :: cat a b -> cat b c -> cat a c
class Category a => Arrow a where
arr :: (b -> c) -> a b c
first :: a b c -> a (b,d) (c,d)
instance Category (->) where
id f = f
instance Arrow (->) where
arr f = f
first f = f *** id
Run Code Online (Sandbox Code Playgroud)
尝试1:模块,简单类型,让绑定
我的第一个镜头是直接使用模块组织来映射事物,例如:
type Arrow<'a,'b> …Run Code Online (Sandbox Code Playgroud) 假设我正在解决一个特定的问题并提出一个函数
let function parameter1 ... =
a lot of adding, multiplying & so on with a lot of
literals all over the place
Run Code Online (Sandbox Code Playgroud)
现在,如果我的参数是 int 类型,这个函数就可以正常工作。但是在某个地方我需要将它提升到 11,我需要额外推动 int64 甚至 BigInteger。那我该怎么办?我复制并粘贴函数,更改名称,并寻找所有使编译器认为函数应该在 int 上运行的文字外观。这很糟糕。
有没有办法做到这一点:
let greatFunction param1 param2 = (param1+1)/(param2*2)
Run Code Online (Sandbox Code Playgroud)
其中 param1 和 param2 可以是整数类型的任何组合?
编辑:
通过下面的 kvb 对一个很棒的提示进行了扩展,我想出了以下内容
module NumericLiteralG
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
let inline FromInt32 n =
let rec loop nIn nOut =
if nIn>0 then loop (nIn - 1) (nOut + …Run Code Online (Sandbox Code Playgroud)