Recursion 递归判别并与映射
我需要一种类型的树和这些树上的地图,所以我这样做:Recursion 递归判别并与映射,recursion,f#,functor,discriminated-union,Recursion,F#,Functor,Discriminated Union,我需要一种类型的树和这些树上的地图,所以我这样做: type 'a grouping = G of ('a * 'a grouping) list with member g.map f = let (G gs) = g gs |> List.map (fun (s, g) -> f s, g.map f) |> G 但这让我想知道: map成员是样板。在Haskell中,GHC将为我实现f
type 'a grouping =
G of ('a * 'a grouping) list
with
member g.map f =
let (G gs) = g
gs |> List.map (fun (s, g) -> f s, g.map f) |> G
但这让我想知道:
map
成员是样板。在Haskell中,GHC将为我实现fmap
(…派生(函子)
)。我知道F#没有类型类,但有没有其他方法可以避免我自己在F#中编写映射let(G gs)=G
我认为没有一种方法可以自动导出
map
,但是有一种方法可以这样编写代码:
#r @"FsControl.Core.dll"
#r @"FSharpPlus.dll"
open FSharpPlus
open FsControl.Core.TypeMethods
type 'a grouping =
G of ('a * 'a grouping) list
with
// Add an instance for Functor
static member instance (_:Functor.Map, G gs, _) = fun (f:'b->'c) ->
map (fun (s, g) -> f s, map f g) gs |> G
// TEST
let a = G [(1, G [2, G[]] )]
let b = map ((+) 10) a // G [(11, G [12, G[]] )]
请注意,map
确实超载了,您看到的第一个应用程序调用了List
的实例。因此,它的行为类似于Haskell中的fmap
还请注意,通过这种方式,您可以分解ggs
,而无需创建let(ggs)=G
现在我想很多人都会同意你的解决方案更为实用,但对我来说,也应该开发新的习语,以获得更多的特征和克服目前的语言限制,这就是为什么我认为使用一个定义明确约定的库也是习惯用法的原因。
无论如何,我同意@kvb的观点,因为将
map
定义到一个模块中稍微更为惯用,在该约定中也使用了,因此您有通用的map
和特定的ModuleX.map
我不认为有自动派生map
的方法,但是有一种方法,您的代码可以这样编写:
#r @"FsControl.Core.dll"
#r @"FSharpPlus.dll"
open FSharpPlus
open FsControl.Core.TypeMethods
type 'a grouping =
G of ('a * 'a grouping) list
with
// Add an instance for Functor
static member instance (_:Functor.Map, G gs, _) = fun (f:'b->'c) ->
map (fun (s, g) -> f s, map f g) gs |> G
// TEST
let a = G [(1, G [2, G[]] )]
let b = map ((+) 10) a // G [(11, G [12, G[]] )]
请注意,map
确实超载了,您看到的第一个应用程序调用了List
的实例。因此,它的行为类似于Haskell中的fmap
还请注意,通过这种方式,您可以分解ggs
,而无需创建let(ggs)=G
现在我想很多人都会同意你的解决方案更为实用,但对我来说,也应该开发新的习语,以获得更多的特征和克服目前的语言限制,这就是为什么我认为使用一个定义明确约定的库也是习惯用法的原因。
不管怎样,我同意@ KVB,在代码中定义<代码> MAP>代码>,在这个约定中也使用了,所以你有通用的<代码>地图>代码>和特定的<代码> MuleX。MAP< /COD> < /P>你考虑了一个让绑定函数<代码>让ReC映射f(G GS)=GS>List.map(Fun(s,g)-f s,map fg)|>G?是的。不过,我想避免这样做:使用
member
的好处似乎是,我避免了用名为mapG
和foldG
之类的东西污染我的本地名称空间。而且我也不会让bind成为会员,对吧?@Sørendbois:这是最好的了。如果您尝试在F#中模拟Haskell,您的代码将比当前(直接的)解决方案复杂得多。@SørenDebois-将其作为分组
模块中的let-bound定义可能更为惯用;然后,你可以打开模块,如果你要使用它很多,并使用<代码>地图<代码>以一种不合格的方式。你考虑了一个让绑定函数<代码>让ReC映射F(G GS)=GS>List.map(Fun(S,G)-F S,MAP FG)>G < /代码>?是的。不过,我想避免这样做:使用member
的好处似乎是,我避免了用名为mapG
和foldG
之类的东西污染我的本地名称空间。而且我也不会让bind成为会员,对吧?@Sørendbois:这是最好的了。如果您尝试在F#中模拟Haskell,您的代码将比当前(直接的)解决方案复杂得多。@SørenDebois-将其作为分组
模块中的let-bound定义可能更为惯用;如果你打算大量使用这个模块,那么你可以打开它,并以一种非限定的方式使用map
。很有趣。你能解释一下或者指出一个我可以去阅读实例(quot:Functor.Map,G gs,quot)
)的地方吗?看看自述文件,我会对你的反馈感兴趣,所以请告诉我你是否认为我可以在解释中添加其他内容。很有趣。你能解释一下或者指出一个我可以去阅读实例(quo;Functor.Map,G gs,quo)
的地方吗?请看一下位于的自述文件,我对你的反馈很感兴趣,所以请告诉我你是否认为我可以在解释中添加其他内容。