一個顯而易見的解決方案是使用bimap
而不是fmap
然後WIRTE在調用者的網站兩次的功能:
type Item<'a, 'b> = Item of 'a * 'b
let transform (i: Item<'a, 'b>) : Item<'a, string> =
let (Item (x, y)) = i
Item (x, sprintf "%A" y)
type X<'a> = {
y: Item<'a, int>
z: Item<'a, bool>
}
with
member inline this.bimap(f, g) =
{
y = f this.y
z = g this.z
}
另一種選擇(這裏的邪惡類型的黑客)是不是傳遞一個函數,通過什麼我稱之爲'Invokable',其中某種函數用一種名爲Invoke
的方法包裝。就像一個委託,但靜態。
下面是一個例子。我用$
代替Invoke
爲了簡單:
let inline fmap invokable ({y = y1; z = z1}) = {y = invokable $ y1; z = invokable $ z1}
type Id = Id with
static member ($) (Id, Item (a,b)) = Item (id a, id b)
type Default = Default with
static member ($) (Default, Item (a:'t,b:'u)) =
Item (Unchecked.defaultof<'t>, Unchecked.defaultof<'u>)
let a = {y = Item ('1', 2); z = Item ('3', true) }
let b = fmap Id a
let c = fmap Default a
現在的問題是,我想不出其他許多有用的功能。你可以嗎?
否則,如果你把它更通用:
type X<'a, 'b, 'c> = {
y: Item<'a, 'b>
z: Item<'a, 'c>
}
,那麼你可以使用例如一個可調用這樣的:
type ToList = ToList with static member ($) (ToList, Item (a,b)) = Item ([a], [b])
let d = fmap ToList a
// val d : X<char list,int list,bool list> = {y = Item (['1'],[2]);
z = Item (['3'],[true]);}
也this related question見。這裏介紹的案例比較簡單,但問題是一樣的。
也this one是相關的。
功能通用性只能在定義。一旦你把它變成「價值」並開始傳遞它,它就會消失。如果您需要保持通用性,請使用界面。 –
所以f應該是任何函數'a - >'a'其中'a可以是一個字符串或bool?除了''id''之外,我可以想象的功能並不多。 – Gustavo