3

F-Sharp가 무한대를 지원하지 않는 이유가 궁금합니다.F-Sharp (F #) 유형 지정되지 않은 무한

이 루비에서 일 것이다 (그러나 F 번호에) :

let numbers n = [1 .. 1/0] |> Seq.take(n) 

-> System.DivideByZeroException은 : 0으로 나눌 시도했습니다.

내가 훨씬 복잡한 방법으로 같은 기능을 쓸 수 있습니다 :

let numbers n = 1 |> Seq.unfold (fun i -> Some (i, i + 1)) |> Seq.take(n) 

을 ->

그러나 내가 첫 번째가 훨씬 더 분명있을 것이라고 생각 작동합니다. F #에서 동적으로 입력 된 무한대를 쉽게 사용할 수있는 방법을 찾을 수 없습니다. 이 무한대 키워드이지만 부동입니다 :

let a = Math.bigint +infinity;; 

System.OverflowException이를 : BigInteger를 무한대의 표시 수 없습니다. 에서 System.Numerics.BigInteger..ctor (Double 값) 에서 은 $ FSI_0045.main @는() 이


편집 오류로 인해 중지 :.

: 또한이 반복에서 작동하는 것 같다
let numbers n = Seq.initInfinite (fun i -> i+1) |> Seq.take(n) 
+0

정수 또는 부동 소수점 연산을 수행합니까? 두 가지는 무한 성의 개념이 크게 다릅니다. –

+0

Ruby에서는 작동하지 않습니다. Infinity는 Ruby에서도 부동 소수점 값이므로 부동 소수점 나누기 - 1..1.0/0을 수행해야합니다. – Chuck

+0

이 특정 사례에서 'let numbers n = seq {1 .. n}'은 가장 간단한 것일 수 있습니다 ... –

답변

8

우선 F # 목록은 게으르지 않습니다. 루비 목록이 게으르다는 것이 확실하지 않습니다. 따라서 일반적인 무한 개념으로도 첫 번째 예제는 작동하지 않습니다.

둘째, Int32에는 무한 값이 없습니다. 오직 MaxValue. Double에는 긍정적이고 부정적인 무한대가 있습니다.

것은 함께 퍼팅이 작동 :

let numbers n = seq { 1. .. 1./0. } |> Seq.take(n) 

나는 그러나 Seq.initInfinite는 당신의 최선의 선택입니다 생각합니다. 위의 코드는 나에게 이상하게 보입니다. (또는 적어도 1.00 대신 Double.PositiveInfinity를 사용하십시오.)

처음에는 언어에 포함시킬 수있는 좋은 옵션은 haskell : seq {1 ..}와 같은 무한 범위 연산자입니다. 문제는 그것은 seq에서만 작동 할 것이므로 postfix 연산자를 지원하는 추가 작업이이 기능만으로는 가치가 없다고 생각합니다.

결론 : 제 생각에는 Seq.initInfinite를 사용하십시오.

+1

Seq.initInfinite는 Int32를 기반으로하므로 실제 용도로 'seq {1 .. System.Int32.MaxValue}'와 동일해야합니다. 대신에 그 구조를 사용하면 아무도 부정이 실제로 관련되어 있다고 믿는 속지 않습니다. 나는 대신 그것을 권하고 싶습니다. - 또는 펼쳐진 접근법 - bigints를 다룰 때 ... –

+0

@ Johan : Seq.initInfinite가 타입 추론과 함께 더 잘 작동한다고 생각합니다. 결과 seq의 유형은 {1..Int32.MaxValue}와는 달리 자동으로 유추되어야합니다. 어떤 상수에 대한 호출이 필요합니다. 따라서 원래의 질문에 더 가까운 해결책이 될 수 있습니다. 그러나 실제로 initInfinite에서 무한한 것은 잘못된 이름입니다. –

3

다음은 F #의 무한 범위에 대한 최상의 솔루션이라고 생각합니다. 함수를 inline으로 표시함으로써 "동적 유형화 된 무한대"보다 나은 결과를 얻습니다. 구조체 형식의 무한 범위 (int32, int64, bigint 등)를 사용할 수 있습니다. 고정 유형 멤버 인 +에는 자체 형식의 두 가지 인수가 사용되며 자신의 유형의 값을 반환 함) :

let inline infiniteRange start skip = 
    seq { 
     let n = ref start 
     while true do 
      yield n.contents 
      n.contents <- n.contents + skip 
    } 

//val inline infiniteRange : 
// ^a -> ^b -> seq< ^a> 
// when (^a or ^b) : (static member (+) : ^a * ^b -> ^a)