F#类型约束-类型变量'a已被约束为类型'b'

时间:2018-11-26 07:08:51

标签: generics f# monads

我正在尝试使一个函数工作,该函数解开信封类型,将一个函数应用于内容并返回一个信封类型。有点像墨西哥卷饼的绑定功能。

type Envelope<'a> =
  { Content : 'a
  ; Errors : string list
  }

let (!>) f e =
    let {Content=content:'a; Errors=errors} = e

    match errors with
    | [] -> e : Envelope<'a>
    | _ -> f content : Envelope<'b>

错误是:

This construct causes code to be less generic than indicated by the type annotations. The type variable 'a has been constrained to be type ''b'.

我有一个“感觉”,为什么会出错,有时我返回Envelope<'a>,而其他时候我返回Envelope<'b>

我该如何使用它?我试图使它像在Option类型上的绑定函数一样“起作用”:

let (>>=) f o =
  match o with
  | Some v -> f v
  | None -> None 

2 个答案:

答案 0 :(得分:3)

问题在于匹配的两种情况都应返回相同的类型,否则在类型系统中就没有意义。

您需要构造一个新的信封,但是我想问题是如果有错误,您不想计算f,因此,这样做的方法很笨拙:

call may violate context's modifies clause

但这不是您想要的,因为您会丢失内容。

正确的方法是使用有区别的联合而不是记录,但是我认为您想要的是始终在发生错误时应用补偿功能,因此在这种情况下,您的补偿功能就不能多态的,因此是原始错误消息。

答案 1 :(得分:0)

在我看来,您正在尝试映射错误或在发生错误的情况下获取默认值。这是几个选项

import UIKit

class MyContentViewController: UIViewController {

    @IBOutlet var theLabel: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        // add 10 lines of text to the label
        theLabel.text = (1...10).map({ "Line \($0)" }).joined(separator: "\n")

    }

}

class ContainerContentViewController: UIViewController {

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        super.prepare(for: segue, sender: sender)

        if let childViewController = segue.destination as? MyContentViewController {
            childViewController.view.translatesAutoresizingMaskIntoConstraints = false
        }
    }

}

此值获取值,如果有错误,则调用该函数以获取默认值。它等效于Sub PullData() Dim IE As New SHDocVw.InternetExplorer Dim hdoc As MSHTML.HTMLDocument Dim HEL As MSHTML.IHTMLElement Dim ha, hb, hc, hd, he, hf, hg, hh, hi, hj As String Dim i, x As Integer i = 2 IE.Visible = True IE.navigate "https://www.nseindia.com/live_market/dynaContent/live_watch/get_quote/GetQuote.jsp?symbol=FEL" Do While IE.readyState <> READYSTATE_COMPLETE Loop Set hdoc = IE.document Set HEL = hdoc.getElementById("tab8") HEL.Click Set HEL = hdoc.getElementById("period") HEL.Value = "3months" Set HEL = hdoc.getElementById("get") HEL.Click End Sub 。它不会返回type Envelope<'a> = { Content : 'a Errors : string list } /// (unit -> 'a) -> Envelope<'a> -> 'a let defaultWith f e = match e.Errors with | [] -> e.Content | _ -> f()

下一个仅在存在错误的情况下,您才能映射错误:

Option.defaultWith

另一方面,这两个如果有错误,则可以映射整个信封。您可以为我刚刚留下的2个主题创建许多变体形式:

Envelope