Новичок f # вопрос - PullRequest
       26

Новичок f # вопрос

3 голосов
/ 08 октября 2010

У меня простой вызов функции занимает два кортежа.Получение ошибки компилятора для типа:

module test

open System.IO
open System

let side (x1,y1) (x2,y2) : float = 
  Math.Sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))

let a = side ( 2s, 3s ) ( 1s, 2s )

Ошибка 2 Тип 'float' не соответствует типу 'int16'

Не уверен, где он идет не так.Кто-нибудь может помочь?

Спасибо!

Ответы [ 3 ]

6 голосов
/ 08 октября 2010

Math.Sqrt ожидает аргумент с плавающей точкой, но вы передаете туда int16. F # не выполняет такие неявные преобразования

let side (x1,y1) (x2,y2) : float = 
    (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)
    |> float
    |> Math.Sqrt

или вы можете передавать поплавки с самого начала:

let side (x1,y1) (x2,y2) : float = Math.Sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1))

let a = side ( 2.0, 3.0 ) ( 1.0, 2.0 )
6 голосов
/ 08 октября 2010

Как уже отмечали другие, компилятор F # не вставляет автоматически какие-либо преобразования между числовыми типами.Это означает, что если вы пишете функцию, которая работает с плавающей точкой, вам нужно передать ее как аргументы.

Функция в вашем примере может работать с различными типами, потому что Math.Sqrt и числовые операторы перегружены.Если вы напишите это без каких-либо аннотаций типов, вы получите функцию, работающую с плавающей точкой (поскольку Math.Sqrt работает только с плавающей точкой):

> let side (x1,y1) (x2,y2) = 
    Math.Sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1));;
val side : float * float -> float * float -> float

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

> let side (x1:int16,y1) (x2,y2) = 
    let n = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)
    Math.Sqrt(float(n));;
val side : int16 * int16 -> int16 * int16 -> float

Нам нужна только аннотация одного типа (затем компилятор выясняет, что y1, x2, ... также должны иметь тип int16потому что мы умножаем / добавляем их, и это разрешено только для двух значений одного типа).Итак, теперь вы можете написать:

side ( 2s, 3s ) ( 1s, 2s ) 

Обратите внимание, что версия от desco немного хитрая - она ​​добавляет функцию преобразования (используя float), но не имеет аннотации типа для указаниятип параметров - в этом случае компилятор выберет тип по умолчанию , который равен int, поэтому, если вы используете его функцию, вам придется вызывать его с помощью side (2,3) (1,2).

3 голосов
/ 08 октября 2010

Сигнатура вашей функции float * float -> float * float -> float, но вы передаете int16 значения (это то, что означает суффикс s).

Один из способов его компиляции состоит в следующем:

let a = side ( 2.0, 3.0 ) ( 1.0, 2.0 )
...