Generics 传递map函数时类型推断不起作用

Generics 传递map函数时类型推断不起作用,generics,dependency-injection,f#,type-inference,Generics,Dependency Injection,F#,Type Inference,首先,;感谢您抽出时间阅读我的问题。如果有任何更多的信息,你需要或想让我改变什么,请让我知道 当我传入一个数组处理函数时,类型推断不起作用,但是当我将函数添加到模块中而不是注入它时,类型推断就起作用了 尝试添加类型注释,但该注释被忽略,F#警告第一次调用时代码不太通用,然后第二次使用错误的类型出错 但如果我改变: let handleAction //following does not work, comment out next line (mapItems : 'a -> '

首先,;感谢您抽出时间阅读我的问题。如果有任何更多的信息,你需要或想让我改变什么,请让我知道

当我传入一个数组处理函数时,类型推断不起作用,但是当我将函数添加到模块中而不是注入它时,类型推断就起作用了

尝试添加类型注释,但该注释被忽略,F#警告第一次调用时代码不太通用,然后第二次使用错误的类型出错

但如果我改变:

let handleAction
  //following does not work, comment out next line
  (mapItems : 'a -> 'b [] -> int -> ('b -> 'a -> 'b) -> 'b [])

那么它就可以正常工作了。试图删除向上的依赖项,但无法让F#理解类型

let mapItems
  action
  state 
  index
  handlerfn =
    state
      |> Array.indexed
      |> Array.map (
        fun (i, item) ->
          if index < 0 then
            handlerfn item action
          else if i = index then
            handlerfn item action
          else
            item)

//Mediator calling the handler for the action
let handleAction
  //following does not work, comment out next line
  (mapItems : 'a -> 'b [] -> int -> ('b -> 'a -> 'b) -> 'b [])
  //notPassedIn //uncomment this and it works 
                //even though mapItems here and mapItems
                //passed in are the exact same code
  state
  action =
    match action with
    |Pausable action -> //actions specific to pausable stopwatch
        let handler = 
          mapItems
            action //warning: less generic
            state
            action.index
        match action.``type`` with
          //... pausable actions (added to support pause/continue)
    | StopWatch action -> //actions from stop watch
        let handler = 
          mapItems
            action//error: wrong type
            state
            action.index
        match action.``type`` with
          //...handling stopwatch actions
让mapItems
行动
陈述
指数
handlerfn=
状态
|>数组索引
|>Array.map(
乐趣(i,项目)->
如果指数<0,则
handlerfn项目操作
否则,如果i=索引,则
handlerfn项目操作
其他的
(项目)
//调用操作处理程序的中介程序
手浸
//以下内容无效,请注释掉下一行
(mapItems:'a->'b[]->int->('b->'a->'b)->'b[]))
//notPassedIn//取消对其注释,它就会工作
//即使这里有mapItems和mapItems
//传入的是完全相同的代码
状态
行动=
配合行动
|可暂停操作->//特定于可暂停秒表的操作
让处理程序=
地图项目
操作//警告:不太通用
状态
动作索引
将操作“`type``与匹配
//... 可暂停操作(添加以支持暂停/继续)
|秒表操作->//来自秒表的操作
让处理程序=
地图项目
操作//错误:类型错误
状态
动作索引
将操作“`type``与匹配
//…处理秒表操作
完整代码如下:

(*
秒表模块
*)
//类型
类型SWActionType=
|整数起点
类型StopWatch动作={
``类型``:SWActionType
//应用程序中可能有多个秒表
索引:int
}
类型起始日期=
|诺沙特
|国际贸易日期
类型SingleStopWatchState={
状态:字符串
}
类型StopWatchState=SingleStopWatchState[]
//秒表操作的处理程序
让handleStart开始当前状态=
{status=“started”}状态为
//秒表调解人
让秒表手动过滤
地图项目
(状态:秒表状态)
(动作:秒表动作)=
让处理程序=
地图项目
行动
状态
动作索引
将操作“`type``与匹配
|启动电流->
处理程序//使用状态调用处理程序
(有趣
(状态:SingleStopWatchState)
(操作:秒表操作)->
(handleStart当前状态)
(*
可暂停秒表,扩展秒表并支持
暂停动作
*)
类型PActionType=
|整数暂停
类型PausableStopWatchAction={
``类型``:PActionType
索引:int
}
型密合=
|秒表动作的秒表
|PausableStopWatchAction的可暂停
类型SinglePausableStopWatchState={
状态:字符串
原因:布尔
}
键入PausableStopWatchState=SinglePausableStopWatchState[]
//可暂停秒表的处理程序
let handlePause current(状态:SinglePausableStopWatchState)=
{以
status=“暂停”
isPaused=true
}
//可暂停秒表调节器
让我们用手洗吧
(mapItems:'a->'b[]->int->('b->'a->'b)->'b[]))
状态
行动=
配合行动
|可暂停操作->//特定于可暂停秒表的操作
让处理程序=
地图项目
//警告:此构造导致代码不像类型注释所指示的那样通用。类型变量“a”已被约束为类型“PausableStopWatchAction”。
行动
状态
动作索引
将操作“`type``与匹配
|暂停当前->
处理程序//使用状态调用处理程序
(有趣
状态
行动->
(handlePause当前状态)
|秒表操作->//来自秒表的操作
让处理程序=
地图项目
(*
错误
此表达式应具有类型
“PausableStopWatchAction”
但这里有一种类型
“秒表行动”
*)
行动
状态
动作索引
将操作“`type``与匹配
|启动电流->
处理程序//使用状态调用处理程序
(有趣
状态
操作->//将在此处使用一些秒表处理程序
{以
status=“已开始”
})
(*
使用秒表和可暂停的应用程序
*)
类型应用程序状态={
秒表:秒表状态
pausablestopwatch:pausablestopwatch状态
}
类型动作=
|秒表动作的秒表
|可暂停秒表
让ArrayHandler
行动
陈述
指数
handlerfn=
状态
|>数组索引
|>Array.map(
乐趣(i,项目)->
如果指数<0,则
handlerfn项目操作
否则,如果i=索引,则
handlerfn项目操作
其他的
(项目)
//应用程序调解人:
手浸
(状态:应用程序状态)
行动=
配合行动
|秒表
行动->
{state with//返回应用程序状态
//使用更新状态设置秒表状态
//由调解人在秒表中提供
秒表=
秒表手浸
ArrayHandler state.stopwatch action}
|可暂停秒表
行动->
{state with//返回应用程序状态
暂停秒表=
可暂停手浸
let mapItems
  action
  state 
  index
  handlerfn =
    state
      |> Array.indexed
      |> Array.map (
        fun (i, item) ->
          if index < 0 then
            handlerfn item action
          else if i = index then
            handlerfn item action
          else
            item)

//Mediator calling the handler for the action
let handleAction
  //following does not work, comment out next line
  (mapItems : 'a -> 'b [] -> int -> ('b -> 'a -> 'b) -> 'b [])
  //notPassedIn //uncomment this and it works 
                //even though mapItems here and mapItems
                //passed in are the exact same code
  state
  action =
    match action with
    |Pausable action -> //actions specific to pausable stopwatch
        let handler = 
          mapItems
            action //warning: less generic
            state
            action.index
        match action.``type`` with
          //... pausable actions (added to support pause/continue)
    | StopWatch action -> //actions from stop watch
        let handler = 
          mapItems
            action//error: wrong type
            state
            action.index
        match action.``type`` with
          //...handling stopwatch actions
(*
  stopwatch module
*)
//types
type SWActionType =
  | Start          of int
type StopWatchAction = {
  ``type``:SWActionType
  //there may be more than one stopwatch in the application
  index:int
}
type StartDate =
  | NoStartDate
  | Date of int
type SingleStopWatchState = {
  status:string
}
type StopWatchState = SingleStopWatchState []
//handlers for the stopwatch actions
let handleStart current state =
  {state with status = "started"}
//mediator for stopwatch
let StopWatchHandleAction 
  mapItems
  (state:StopWatchState)
  (action:StopWatchAction) =
    let handler = 
      mapItems
        action
        state
        action.index
    match action.``type`` with
      | Start current ->
          handler//call handler with state
            (fun
              (state:SingleStopWatchState)
              (action:StopWatchAction) ->
                (handleStart current state))
(*
  Pausable stopwatch that extends stopwatch and supports
  pause action
*)
type PActionType =
  | Pause          of int
type PausableStopWatchAction = {
  ``type``:PActionType
  index:int
}
type PAction =
  | StopWatch of StopWatchAction
  | Pausable of PausableStopWatchAction
type SinglePausableStopWatchState = {
  status:string
  isPaused:bool
}
type PausableStopWatchState = SinglePausableStopWatchState []
//handlers for pausable stopwatch
let handlePause current (state:SinglePausableStopWatchState) =
  {state with 
    status = "paused"
    isPaused = true
  }
//mediator for pausable stopwatch
let PausableHandleAction
  (mapItems : 'a -> 'b [] -> int -> ('b -> 'a -> 'b) -> 'b [])
  state
  action =
    match action with
    |Pausable action -> //actions specific to pausable stopwatch
        let handler = 
          mapItems
            //warning:This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type 'PausableStopWatchAction'.
            action
            state
            action.index
        match action.``type`` with
          | Pause current ->
              handler//call handler with state
                (fun
                  state
                  action ->
                    (handlePause current state))
    | StopWatch action -> //actions from stop watch
        let handler = 
          mapItems
            (*
              ERROR
              This expression was expected to have type
              'PausableStopWatchAction'    
              but here has type
              'StopWatchAction'
            *)
            action
            state
            action.index
        match action.``type`` with
          | Start current ->
              handler//call handler with state
                (fun
                  state
                  action -> //would use some of stopwatch handlers here
                    {state with
                      status ="started"
                    })
(*
  Application consuming stopwatch and pausable
*)
type ApplicationState = {
  stopwatch:StopWatchState
  pausablestopwatch:PausableStopWatchState
}
type Action =
  | StopWatch of StopWatchAction
  | PausableStopWatch of PAction
let ArrayHandler
  action
  state 
  index
  handlerfn =
    state
      |> Array.indexed
      |> Array.map (
        fun (i, item) ->
          if index < 0 then
            handlerfn item action
          else if i = index then
            handlerfn item action
          else
            item)
//application mediator:
let handleAction 
  (state : ApplicationState)
  action =
  match action with
    | StopWatch
        action ->
          {state with//return application state
            //set the stopwatch state with updated state
            //  provided by the mediator in stop watch
            stopwatch = 
              StopWatchHandleAction
                ArrayHandler state.stopwatch action}
    | PausableStopWatch 
        action ->
          {state with//return application state
            pausablestopwatch = 
              PausableHandleAction
                ArrayHandler state.pausablestopwatch action}
let mkList x = [x]
let mkTwo (f: 'a -> 'a list) = (f 42), (f "abc")
let two = mkTwo mkList
let mkTwo<'a> (f: 'a -> 'a list) = (f 42), (f "abc")
let mkList x = [x]
let mkTwo f g = (f 42), (g "abc")
let two = mkTwo mkList mkList
type MkList =
    abstract member mkList : 'a -> 'a list

let mkList = { new MkList with member this.mkList x = [x] }
let mkTwo (f: MkList) = (f.mkList 42), (f.mkList "abc")
let two = mkTwo mkList
let mapItems
  state 
  index
  handlerfn =
    state
      |> Array.indexed
      |> Array.map (
        fun (i, item) ->
          if index < 0 then
            handlerfn item 
          else if i = index then
            handlerfn item 
          else
            item)

...

let handleAction
  (mapItems : 'a [] -> int -> ('a -> 'a) -> 'a [])
  state
  action =
    match action with
    |Pausable action -> //actions specific to pausable stopwatch
        let handler = 
          mapItems
            state
            action.index
        match action.``type`` with
         | Pause current ->
             handler//call handler with state
               (fun state ->
                     (handlePause current state))
    | StopWatch action -> //actions from stop watch
       let handler = 
         mapItems
           state
           action.index
       match action.``type`` with
         | Start current ->
             handler//call handler with state
               (fun state ->
                   //would use some of stopwatch handlers here
                   {state with
                     status ="started"
                   })