Re: [F#] Unit type
От: samius Япония http://sams-tricks.blogspot.com
Дата: 21.07.09 18:39
Оценка: 12 (1)
Здравствуйте, Пельмешко, Вы писали:

П>Размышлял на досуге, зачём введён тип unit в F#...

П>Причём это не просто синоним void, а обычный класс Microsoft.FSharp.Core.Unit, да ещё и с int _dummy внутри
П>Хотя unit никогда не создаётся, всегда возвращается адресный null...

Я этот вопрос себе тоже задавал, пришел к следующим выводам:
Нужен был просто именно значение некоторого типа, которое никому не интересно. Т.е. само значение есть, но что именно там — не важно. И это как раз отличает его от void-а, который есть "ничто", т.е. даже значения его нет.

П>Должен же быть смысл, какую-нибудь проблему это решает

Конечно решает!
Имея такой тип, можно комбинировать в штатном порядке функции, принимающие и возвращающие unit. С void-ом такое не прокатит.

П>Я понимаю, что в ФП функции обязаны возвращать что-либо, но зачем вводить отдельный тип, если можно

П>
| 1 -> ()
за сценой превращать в:

П>
case 1: return;

нет, void нас не устраивает, т.к. функция должна возвращать хоть что-нибудь.

П>Как то читал Эрика Липперта про вариантность void, подумал по началу, что unit — просто уловка, вариантный аналог void'а. Проверил — это не так...


именно к вариантности не имеет отношения, как мне кажется.

П>Пока писал этот пост пришло в голову, что может unit нужен для поддержки функциональных типов, всяким FastFunc<T1,T2> нельзя же указать System.Void в качестве generic-параметра...

А вот это — оно самое. Здесь нам не надо подразделять на Func<T,...> и Action<T,...>. Всегда обходимся одним способом.

П>Я правильно понимаю предназначение unit?

Вобщем — да. Это заменитель void, но более гибкий.

Правда есть один трюк, который я не до конца понимаю.
> ignore;;
val it : ('a -> unit) = <fun:clo@0>


при том, что сигнатура метода ignore в рефлекторе определена как
public static void ignore<T>(T value)


Т.е. void интерпретируется как и unit.

Но не совсем:
> let f1 () = ()
- let f2 () = ()
- let f3 = f1 >> f2;;

val f1 : unit -> unit
val f2 : unit -> unit
val f3 : (unit -> unit)

объявленные так функции мы можем комбинировать.

и так тоже:
> let f4 = f1 >> ignore;;  

val f4 : (unit -> unit)


а так уже нельзя:
> let f5 = ignore >> f1;; 

  let f5 = ignore >> f1;;
  ----^^

stdin(15,5): error FS0030: Value restriction. The value 'f5' has been inferred to have generic type
        val f5 : ('_a -> unit)
Either make the arguments to 'f5' explicit or, if you do not intend for it to be generic, add a type annotation.
>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.