[英]Why a string is interned that is created via constructor and with a char[]?
[英]Why would the signature be … -> Result<char*string>?
我正在關注斯科特的講話 ,他帶來的一個例子是:
type Result<'a> =
| Success of 'a
| Failure of string
let pchar (charToMatch, input) =
if System.String.IsNullOrEmpty (input) then
Failure "no input!"
else
let first = input.[0]
if first = charToMatch then
let remaining = input.[1..]
Success (charToMatch, remaining)
else
let msg = sprintf "exepecting '%c' got '%c'" charToMatch first
Failure msg
Visual Studio Code顯示pchar
函數的簽名是:
char*string->Result<char*string>
:
返回類型應該只是Result<'a>
嗎?
Result<'a>
是一個泛型類型,它具有'a
作為類型參數。 當您編寫Success (charToMatch, remaining)
編譯器會將此泛型類型參數推斷為char
和string
的元組: Result<char*string>
。 您可以編寫Success ()
然后您將獲得Result<unit>
類型。
同樣在F#中,當您使用逗號(charToMatch, input)
在括號中列出函數的參數時,這意味着您的函數期望一個元組,這意味着您不能使用currying 。 要使let pchar charToMatch input = ...
可用,你應該定義這樣的函數: let pchar charToMatch input = ...
這里的想法是您可以使用Result
類型來包裝任何操作的結果,以便您可以使用業務邏輯對控制流進行建模。 這在“業務錯誤”和“例外”之間存在重疊的情況下尤其有用。 在您的示例中,一次解析一個字符串,並且該函數返回解析后的字符以及字符串的其余部分(作為F#Tuple)。
Result
是泛型類型,因此它可以表示任何操作的結果。 如果Result
類型的'a
type-parameter的值不返回Result
則它將與函數的返回類型相同。 考慮一個如下的簡單示例:
let f () = ('t', "est")
編譯器告訴我們它有類型簽名unit -> char * string
。 那是因為函數總是采用一個unit
(空/無效)參數並返回一個單個字符和一個字符串的元組。 如果我們稍微更改該函數以返回Result
,如下所示:
let f () = ('t', "est") |> Success
現在編譯器告訴我們簽名是unit -> Result<char * string>
。 與函數的原始返回類型相同,包含在Result
類型中。 您的示例是相同的,除了返回的字符和字符串元組基於輸入參數,並且如果輸入參數為null或空字符串,則函數可以返回失敗。
如果定義一個“解包”結果並將其中的值傳遞給另一個函數的bind
函數,則可以輕松使用Result
類型, f
:
let bind f = function
| Success s -> f s
| Failure f -> Failure f
使用bind
,您可以輕松地將pchar
調用的結果傳遞給另一個使用該值的函數,而該函數不必顯式獲取Result
類型:
let printChar (c, str) =
printfn "Matched Char %A, Remaining String: '%s'" c str
pchar ('a', "aaab") |> bind (printChar >> Success)
我經常使用這種模式,但是我在Result
類型中添加了第二個泛型參數,表示函數的events
或effects
。 這通過允許我們具有可以在代碼中處理的特定Failure
事件(而不是檢查特定字符串),或通過包含域事件(例如警告)或副作用以及我們的成功結果來增加Result
類型的效用。
我為此使用了一個名為OperationResult
的類型,以避免與內置的F# Result
類型混淆。 由於我有時會包含事件/效果成功結果以及失敗,因此我為SuccessfulResult
定義了一個類型,它只是返回值,或返回值以及事件列表。 總之,它提供了以下類型來定義OperationResult
:
/// Represents the successful result of an Operation that also yields events
/// such as warnings, informational messages, or other domain events
[<Struct>]
type SuccessfulResultWithEvents<'result,'event> =
{
Value: 'result
Events: 'event list
}
/// Represents the successful result of an Operation,
/// which can be either a value or a value with a list of events
[<Struct>]
type SuccessfulResult<'result,'event> =
| Value of ResultValue: 'result
| WithEvents of ResultWithEvents: SuccessfulResultWithEvents<'result,'event>
member this.Result =
match this with
| Value value -> value
| WithEvents withEvents -> withEvents.Value
member this.Events =
match this with
| Value _ -> []
| WithEvents withEvents -> withEvents.Events
/// Represents the result of a completed operation,
/// which can be either a Success or a Failure
[<Struct>]
type OperationResult<'result,'event> =
| Success of Result: SuccessfulResult<'result,'event>
| Failure of ErrorList: 'event list
如果您想使用它,我將所有這些打包在GitHub (和NuGet )的庫中以及稱為operation
的Computation Expression中。 GitHub頁面也有一些例子。
@kagetoki是正確的,F#從使用中推斷出類型。
此外,這看起來像一個解析器組合庫。 pchar
的目的是嘗試從輸入中提取字符。 如果成功返回字符和字符串的其余部分,則表示char*string
的自然方式。 這包含在Result
以支持失敗,因此最終返回類型應為: Result<char*string>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.