2017-02-11 13 views
0

Имеет ли двоеточие, за которым следует тип в конце подписи, другое значение в зависимости от того, добавлено ли оно к функции по сравнению с методом?Имеет ли двоеточие, за которым следует тип в конце подписи, имеет другое значение, основанное на контексте?

Это связано с question Я отправил в прошлом. Однако этот вопрос основывался на контексте метода .

Для примера возьмем следующие функции:

type StateResponse<'state, 'event> = ('state * 'event) -> 'state 

// Account * Event -> Account 
let update1 : StateResponse<Account,Event> = function 
    | account , LoggedIn credentials -> account 
    | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
    | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

// Account ** Doesn't compile** 
let update2 : Account = function 
    | account , LoggedIn credentials -> account 
    | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
    | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

// Account * Event -> Account 
let update3 = function 
    | account , LoggedIn credentials -> account 
    | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
    | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

// state:Account * event:Event -> Account 
let update4 (state , event) = 
    match state , event with 
    | account , LoggedIn credentials -> account 
    | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
    | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

// state:StateResponse<Account,Event> * event:Event -> StateResponse<Account,Event> ** Doesn't compile** 
let update5 (state , event) : StateResponse<Account,Event> = 
    match state , event with 
    | account , LoggedIn credentials -> account 
    | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
    | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

Функция Контекст - Обозначает псевдоним функции?

Я полагаю, что, когда после двоеточия типа функции добавляются к концу имени функции, то, что имя функции становится псевдонимом к типуфункции, которая приходит после двоеточия. Это то же самое соглашение, которое используется для предоставления псевдонимов для параметров функции или элементов кортежа.

Примечание:

Я предполагаю, что тип, который не отражает функцию не может не быть добавлен после толстой кишки функции подписи (т.е. Update2).

У меня также есть причина полагать, что имя функции, которое псевдонизирует сигнатуру функции, не может иметь явные параметры, объявленные перед двоеточием (то есть update5).

Метод Контекст - обозначает тип возврата?

Я полагаю, что, когда двоеточие следует типа добавляется в конец имени метода с последующим параметрам, то этот тип, который добавляется в конце концов может быть произвольный тип (независимо от того, если это функция подписи). Это противоречит контексту функции, если применяется.

Являются ли мои предположения точными?

Приложение:

namespace Domain 

module EventSourcing = 

    type StateResponse<'state, 'event> = ('state * 'event) -> 'state 

module Account = 

    open EventSourcing 

    type AccountId = AccountId of string 
    type FirstName = FirstName of string 
    type LastName = LastName of string 

    type Credentials = { UserId:string; Password:string } 
    type Account = { 
     AccountId: AccountId 
     FirstName: FirstName 
     LastName: LastName 
     Balance: decimal } 

    and Event = 
     | LoggedIn of Credentials 
     | Deposited of balance: decimal 
     | Withdrew of balance: decimal 

    (*Functions*) 
    let getAccount credentials = { 
     AccountId= AccountId "myAccountId" 
     FirstName= FirstName "Scott" 
     LastName= LastName "Nimrod" 
     Balance= 20000m } 

    let update1 : StateResponse<Account,Event> = function 
     | account , LoggedIn credentials -> account 
     | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
     | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

    let update2 : Account = function 
     | account , LoggedIn credentials -> account 
     | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
     | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

    let update3 = function 
     | account , LoggedIn credentials -> account 
     | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
     | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

    let update4 (state , event) = 
     match state , event with 
     | account , LoggedIn credentials -> account 
     | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
     | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

    let update5 (state , event) : StateResponse<Account,Event> = 
     match state , event with 
     | account , LoggedIn credentials -> account 
     | account , Deposited balance  -> { account with Balance=account.Balance + balance } 
     | account , Withdrew balance  -> { account with Balance=account.Balance - balance } 

ответ

6

двоеточие обозначает тип того, что осталось от него. Поэтому, когда вы пишете let x : T = ..., вы говорите, что тип x - T. Здесь T должен соответствовать типу, который приходит после =. Так что если это функция, T должен быть совместимым типом функции, если это что-то еще, T должно быть что-то еще.

Например let x : int = 42 и let x : int -> int = function y -> y+1 являются действительными в то время как let x : int -> int = 42 или let x : int = function y -> y+1 не будет, потому что 42 не имеет типа int -> int и function y -> y+1 не имеет типа int.

Теперь, когда вы используете синтаксис ярлыка для определения функций, например let f (x: ParameterType) : T, то, что осталось от последнего двоеточия, является f(x : ParameterType), а не f. Итак, теперь вы говорите, что такое тип f(x) (или, другими словами, какой тип возврата f есть), а не тип f. И снова этот тип должен соответствовать типу того, что приходит после =.

PS: Оба let f = function x -> ... (или в этом отношении let f = fun x -> ...) и let f x = ... являются в точности эквивалентными и определяют функции. Методы определяются с использованием ключевого слова member и, похоже, не связаны с вашим вопросом.