我试图让我的头围绕F#中的monads,我正在寻找一个组合它们的例子.
在haskell中看起来你会使用Monad Transformers但在F#中看起来你会创建自己的计算表达式构建器.
我可以支持这一点,但有没有标准monad的一些组合的例子以及如何使用它们?
我特别感兴趣的是将Reader,Writer和Either结合起来构建接受环境的函数,调整它,然后使用Writer将更改返回到发生的环境中.两者都可用于区分成功与失败.
现在,获得一个产生值+ log或错误的EitherWriter计算表达式的例子会很棒.
我想创建一个定义类型的类型:
type LeftRight<'left, 'right> = {
Left : 'left list
Right : 'right list
}
Run Code Online (Sandbox Code Playgroud)
和几个功能:
let makeLeft xs = { Left = xs; Right = [] }
let makeRight ys = { Left = []; Right = ys }
Run Code Online (Sandbox Code Playgroud)
我想提供一个'组合器'功能:
let combine l r = { Left = l.Left @ r.Left; Right = l.Right @ r.Right }
Run Code Online (Sandbox Code Playgroud)
当我尝试做某事时,我(显然!)因为我的价值是通用的而得到问题:
let aaa = makeLeft [1;2;3]
// Value restriction. The value 'aaa' has been inferred to have generic type
// val aaa …Run Code Online (Sandbox Code Playgroud) 我正在使用FsCheck在F#中进行一些属性测试.因此,无论输入参数如何,我都希望保证某些条件始终存在.
考虑我为float值定义一个简单的标识函数.
let floatId (x : float) = x
Run Code Online (Sandbox Code Playgroud)
然后我定义了这个函数的测试,我知道应该总是这样:
let ``floatId returns input float`` x = floatId x = x
Run Code Online (Sandbox Code Playgroud)
这是一个简单的测试,我只是检查调用我的float identity函数返回与输入float相同.
然后我将此函数插入FsCheck:
Check.Quick ``floatId returns input float``
Run Code Online (Sandbox Code Playgroud)
不幸的是,这个属性测试失败!
Run Code Online (Sandbox Code Playgroud)Falsifiable, after 21 tests (0 shrinks) (StdGen (1872424299,296201373)): Original: nan
当然,回顾过去,很明显这将会发生,我们知道nan <> nan.
由于F#中的结构比较,这可能会困扰(稍微)涉及集合的更复杂的测试案例.
如果我为浮点列表设计一个类似的函数:
let listFloatId (lst : float list) = lst
let ``listFloatId returns input float list`` lst = listFloatId lst = lst
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)Falsifiable, after 6 tests (3 shrinks) (StdGen (1874889363,296201373)): Original: [nan; 2.0; …
我有一个 ICollection,需要将其转换为 F# 列表。如果集合是强类型的,即 ICollection<'T>,很明显我可以写:
let myList = List.ofSeq myCollection
Run Code Online (Sandbox Code Playgroud)
但是如何对弱类型集合执行此操作呢?