当前位置:   C++ > 正文

F#中的免费Monad,具有通用输出类型

monads,f#,free-monad,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发人员工具,站长工具

我正在尝试应用F#中描述的免费monad模式以实现数据访问的乐趣和利益(对于Microsoft Azure表存储)

假设我们有三个数据库表和三个dao的Foo,Bar,Baz:

Foo          Bar          Baz

key | col    key | col    key | col
---------    ---------    ---------
foo |  1     bar |  2         |

我想用key ="foo"选择Foo,用key ="bar"选择Bar,用key ="baz"和col = 3插入一个Baz

Select ("foo", fun foo -> Done foo)
  >>= (fun foo -> Select ("bar", fun bar -> Done bar)
    >>= (fun bar -> Insert ((Baz ("baz", foo.col + bar.col), fun () -> Done ()))))

在解释器功能内

Select导致一个函数调用,它接受一个key : string并返回一个obj

Insert导致一个函数调用,它接受obj并返回unit

问题

我定义了两个操作Select,Insert除了Done终止计算:

type StoreOp<'T> =
  | Select of string * ('T -> StoreOp<'T>)
  | Insert of 'T * (unit -> StoreOp<'T>)
  | Done of 'T

为了链接StoreOp,我试图实现正确的绑定功能:

let rec bindOp (f : 'T1 -> StoreOp<'T2>) (op : StoreOp<'T1>) : StoreOp<'T2> =
  match op with
  | Select (k, next) ->
      Select (k, fun v -> bindOp f (next v))
  | Insert (v, next) ->
      Insert (v, fun () -> bindOp f (next ()))
  | Done t ->
      f t

  let (>>=) = bindOp

但是,f#编译器正确警告我:

The type variable 'T1 has been constrained to be type 'T2

对于bindOp的这个实现,类型在整个计算过程中是固定的,因此不是:

Foo > Bar > unit

我只能表达的是:

Foo > Foo > Foo

在整个计算过程中,如何修改StoreOp和/或bindOp的定义以使用不同的类型?



1> Tomas Petric..:

正如Fyodor在评论中提到的那样,问题在于类型声明。如果要以牺牲类型安全为代价进行编译,则可以obj在两个地方使用-至少可以显示问题出在哪里:

type StoreOp<'T> =
  | Select of string * (obj -> StoreOp<'T>)
  | Insert of obj * (unit -> StoreOp<'T>)
  | Done of 'T

我不完全确定这两个操作应该建模的方式-但是我想这Select意味着您正在读取某些内容(使用string键?),并且Insert意味着您正在存储一些值(然后继续进行unit)。因此,在这里,您要存储/读取的数据将是obj

有多种使这种类型安全的方法,但是我认为如果您解释了通过使用Monadic结构要实现的目标,将会得到更好的答案。

如果不了解更多信息,我认为使用免费的monad只会使您的代码非常混乱并且难以理解。F#是一种功能优先的语言,这意味着您可以使用不变的数据类型以优美的功能风格编写数据转换,并使用命令式编程来加载数据和存储结果。如果您正在使用表存储,为什么不编写普通的命令性代码以从表存储中读取数据,将结果传递给纯函数转换,然后存储结果呢?


我同意分离纯净的代码和不纯净的代码是可取的,但是免费的monad是这样做的一种糟糕方法。最终,该代码无论如何都是不纯净的-免费的monad允许您做的是抽象出杂质的处理方式-我认为这样做没有任何好处。(您可能会说这对测试很有用,但我认为这只是掩盖了您应该测试的关键部分的测试,而这正是对数据的操作。)如果要实现特定的目标,那么有更好的选择做到这一点的方法。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/CPP/detail/14225
推荐阅读
  • 如何解决《此搜索方法中IComparable和IComparable<T>之间的差异》经验,为你挑选了1个好方法。c#,icomparable,icomparablet,windows,安全,DevBox,在线流程图,编程,编程... [详细]

  • 如何解决《通用类型转换FROM字符串》经验,为你挑选了4个好方法。c#,generics,primitive,type-safety,安全,go,hive,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析... [详细]

  • 如何解决《NumPy:将'np.save()'与'allow_pickle=False'一起使用的后果》经验,为你挑选了1个好方法。python,numpy,安全,DevBox,在线流程图,编程,编程问答,程... [详细]

  • 如何解决《Java:如何从字符串生成PrivateKey?》经验,为你挑选了1个好方法。security,android,rsa,private-key,安全,vb,go,css,DevBox,在线流程图,编程,编程问答,程序员,开发者工具... [详细]

  • 如何解决《开发人员测试与QA团队测试-什么是正确的工作分工?》经验,为你挑选了3个好方法。testing,unit-testing,qa,process,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json... [详细]

  • 如何解决《关于C#和VB.net相似/差异的访谈问题》经验,为你挑选了1个好方法。c#,vb.net,vb,程序员,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线... [详细]

  • 如何解决《我应该避免哪些C++陷阱?》经验,为你挑选了9个好方法。c++,stl,安全,spark,go,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开... [详细]

  • 如何解决《Kotlin中的正则表达式匹配》经验,为你挑选了1个好方法。regex,kotlin,安全,html,javascript,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix... [详细]

  • 如何解决《你如何在C中产生另一个进程?》经验,为你挑选了4个好方法。c,process,windows,linux,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线... [详细]

  • 如何解决《为什么没有用于获取当前活动的AndroidAPI?》经验,为你挑选了0个好方法。android,android-intent,android-service,android-activity,安全,https,html,DevBo... [详细]

  • 如何解决《ActiveMQ发送ObjectMessage》经验,为你挑选了1个好方法。security,activemq,安全,apache,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,... [详细]

  • 如何解决《功能参数的C地址?》经验,为你挑选了1个好方法。c,arm,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发人员工具,站长工具... [详细]

  • 如何解决《限制Firebase数据库访问一个Android应用程序》经验,为你挑选了0个好方法。android,firebase,firebase-security,firebase-realtime-database,安全,go,json... [详细]

  • 如何解决《在'gitpull`上自动触发`gitprune`?》经验,为你挑选了1个好方法。git,go,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开... [详细]

  • 如何解决《你如何保护database.yml?》经验,为你挑选了3个好方法。security,deployment,ruby-on-rails,ruby,mysql,服务器,ssh,安全,机器人,git,https,DevBox,在线流程图... [详细]

  • 如何解决《使用puma-dev获取本地的SSL/httpsforRails》经验,为你挑选了1个好方法。ruby-on-rails,keychain,puma,https,chrome,安全,rust,DevBox,在线流程图,编程,编程问... [详细]

  • 如何解决《x86处理器如何"识别"多个进程的运行?》经验,为你挑选了1个好方法。cpu,x86,assembly,operating-system,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发... [详细]

  • 如何解决《有没有办法让LinqPad使用EFCore上下文?》经验,为你挑选了2个好方法。linqpad,entity-framework-core,sql,安全,json,服务器,DevBox,在线流程图,编程,编程问答,程序员,开发者工... [详细]

  • 如何解决《VisualStudio2015非常慢》经验,为你挑选了5个好方法。c#,visual-studio-2015,windows,asp.net,编辑器,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,... [详细]

  • 如何解决《AutoFac:注入NULL值》经验,为你挑选了1个好方法。c#,null,autofac,注入,安全,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具... [详细]

相关标签
  

闽ICP备14008679号