How to Implement an Money Type in Ada? - wsdl

I Try to convert Following Ada Code Package with ada2wsdl
package Bank is
type Money is new Float; -- works
type Money is delta 0.01 digits 15; -- dont work
end Bank;
The Command Line Tool gives following output
ada2wsdl: unsupported element kind Money
How i should implement the Money Type in Ada ?
Is That correkt ?

Because XML Schema has no fixed-point or binary-coded decimal (BCD) type, in the xsd: namespace, ada2wsdl was designed with the destination xsd type as the 1st-class citizen and the corresponding Ada type derived from that. Floating point should never be utilized for money because floating point can be imprecise in the least-significant digits for large amounts of money that are expected to be accurate right down to the last 0.01 monetary unit. The closest emulation in XML Schema for Ada's fixed-point type would be a string in the WWW UI delivered to Ada via the ada2wsdl as a string then converted in Ada code to Ada's fixed-point type.
Also (especially for a bank), the Money type should always contain an accompanying monetary unit along with the fixed-point number as an Ada record.
package Bank is
type IdMonetaryUnit is (EUR, GBP, RUB, USD);
type StrMoney is String(1..15); -- Use this in wsdl with radix-point implicitly implied at 0000000000000.00 for "000000000000000".
type Money is
record
Value : delta 0.01 digits 15;
IdUnit : IdMonetaryUnit;
end record;
end Bank;
For a bank, I would recommend more than 15 digits. I think that 18 is the bare minimum in the real world when considering all monetary units used in banking; certainly some ISO or banking-industry standard would specify that minimum field size for use in practice.

type Money is delta 0.01 digits 18;
Result: 36553462709287.80 EUR -> ok
Result: 18287169236628.28 EUR -> ok
Result: 12193767453669.50 EUR -> ok
Result: 9146196324860.35 EUR -> ok
Result: 7317375076173.70 EUR -> ok
Result: 6098044816860.81 EUR -> ok
Result: 5227037762542.62 EUR -> ok
Result: 4573751368852.46 EUR -> ok
Result: 4065621296766.90 EUR -> ok
Result: 3659105626024.01 EUR -> ok
php7 float
Result: 36553462709288.00 EUR -> false
Result: 18287169236628.00 EUR -> false
Result: 12193767453670.00 EUR -> false
Result: 9146196324860.40 EUR -> false
Result: 7317375076173.70 EUR -> ok
Result: 6098044816860.80 EUR -> false
Result: 5227037762542.60 EUR -> false
Result: 4573751368852.50 EUR -> false
Result: 4065621296766.90 EUR -> ok
Result: 3659105626024.00 EUR -> false

Related

Representing a Floating Point with Discriminated Unions and Record Types

For my project, it’s necessary to “decompose” IEEE 754 floating point types into an internal representation. I have the following types:
type Sign =
| Positive
| Negative
type Number =
{ exponent: int32 // The exponent is de-biased when converting from floating-point types. Exponent values here range from −2,147,483,648 to 2,147,483,647.
mantissa: bigint } // There is no implicit leading 1 bit. If the original float was normal, the converting code prepends the originally hidden 1 bit to the mantissa. Subnormals do not have this bit prepended to the mantissa.
type Infinity = Infinity
type SuperFloat =
| Number of Sign * Number
| Infinity of Sign * Infinity
| NaN
Could this have been better written using some syntactic shortcut to save on types, or is this the minimal amount of types I have to put up with to cover all the possible kinds of floats?
NaN payloads do not need to be supported.
The internal representation is not exposed to outside code and require no interoperability with other .NET languages.
First, the Infinity type is not really useful: because it only has one value, it doesn't encode any information.
Then, you don't need Sign under the Number case, because number itself has sign "baked in" - i.e. mantissa can be negative (by the way, for this reason your representation is not just overkill, but actually incorrect).
So the second iteration would be:
type Sign =
| Positive
| Negative
type Number = {
exponent: int32
mantissa: bigint }
type SuperFloat =
| Number of Number
| Infinity of Sign
| NaN
The next point is arguable and depends on intended usage, but I personally would get rid of the Sign type and encode the infinity sign with two separate cases instead:
type Number = {
exponent: int32
mantissa: bigint }
type SuperFloat =
| Number of Number
| PositiveInfinity
| NegativeInfinity
| NaN
And finally, you could bring the exponent and mantissa directly under the DU if you want, but that one is even more arguable and even more depends on usage:
type SuperFloat =
| Number of exponent: int32 * mantissa: bigint
| PositiveInfinity
| NegativeInfinity
| NaN
Update
Since I was reminded in the comments that negative zero is a thing, I have to bring back the Sign type after all. And since it's here anyway, we can use it for infinity, too:
type Sign = Positive | Negative
type SuperFloat =
| Number of sign: Sign * exponent: int32 * mantissa: bigint
| Infinity of Sign
| NaN
However, keep in mind that this type allows incorrect values, because the mantissa can still be negative. Unfortunately, bigint can't be made non-negative.
I assume there is a reason for making mantissa a bigint (do you need to work with arbitrarily large numbers?), but if there is no specific reason, I would recommend going with uint64 instead. It will be more than enough to encode double-precision floating-point numbers.

F# Sequences and Records

I have 2 sequences...
type Suit = Spades | Clubs | Hearts | Diamonds
type Rank = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King
type Card = { suit: Suit; rank: Rank}
and intValueCard = {rank: Rank; value: int} // translates the union into an actual int
and just wondering how I can get the Card's Rank in an actual int... so far I have
let getActualValue (card:Card) =
value |> translatedValue.Rank
but for the life of me I can't figure out how to deal with a sequence and getActualValue doesn't work..
I don't see any sequences. You have Suit and Rank which are discriminated unions, and you have Card which is a record. Not sure what you meant by intValueCard = {rank: Rank; value: int}, and getActualValue refers to a translatedValue which isn't explained. What will the integer value from the rank be used for? You can possibly get better help if you edit and improve your question.
Let's assume you want the rank in order to calculate the advantage in a game. It is probably best to create a function like this.
let weightFromRank rank =
match rank with
| Ace -> 1
| Two -> 2
...etc...
You can use the function keyword to make a less verbose version of this function.
I believe it is not a good idea to use an enum, because you will miss out on important advantages of functional programming. Enum is a .NET type, and not a functional type.
Different kinds of games have different kind of weights on Ace. Some games give Ace a weight of 14, one above the King. You can then have different functions for calculating the weight, depending on what kind of game is played.
Take the following advice with a grain of salt, since I'm not a top notch expert on F#. A different approach would be to put the weight as a separate field in a record or a discriminated union or something like that. This approach I believe is less efficient, because the weight follows from the rank, so you would effectively be duplicating information in places where it's not needed, thereby also making your code more difficult to understand. It would also be less efficient to handle different weights for different kinds of games.
You can declare Rank as a enum:
type Rank =
| Ace = 1
| Two = 2
| Three = 3
....
then use int to get the underlying value:
let getActualValue ({rank = r}) = int r
If you want the integer rank for comparison with other ranks, then you can just compare the discriminated union values instead, as comparison is built into them for free:
Eight < Nine // true
Jack < Six // false
[Seven; Ace; Four; Two] |> List.sort
// [Ace; Two; Four; Seven]
Now, if you really need the integer rank value for some reason you could use reflection to get the DU cases. Just make sure that you that you do it inside a top level module value, not inside a function, so that the reflection is only done once when the program starts:
open FSharp.Reflection
let ranks =
FSharpType.GetUnionCases(typeof<Rank>)
|> Array.map (fun c -> FSharpValue.MakeUnion(c, [||]) :?> Rank)
let getActualValue rank = Array.findIndex ((=) rank) ranks
getActualValue Ace // 0
getActualValue Two // 1
getActualValue King // 12

Modeling domain type

A limit price has a decimal value. A Market price does not.
How do I model this in F#?
module TradingDomain
let NoPrice = None
type PriceActionType =
| Limit of decimal
| Market of NoPrice
You can just not give Market any arguments:
type PriceActionType =
| Limit of decimal
| Market
There are a couple of ways to go about it, but if you do domain modelling it's a good idea to have an understanding of all the components, in this case, 1) how traders think about the order, 2) how FIX (if that's what's being used) thinks about the order, and 3) how the market you trade thinks about the order. Btw, there's this book that you might find useful. Also, Chapter 7 in F# Deep Dives.
That said Tarmil's answer should work for you, and here but I have two comments. Sometimes it's better to be explicit about the type and use .NET types. float and decimal are F# aliases and they might refer to the function that casts to float. There is also the possibility to use Some and None for expressing the price. So here's a version that includes the orderside as well:
type Price =
| Limit of Decimal
| Market
type OrderSide =
| Buy of Price
| Sell of Price
| ShortSell of Price
You can use it like this: Buy (Limit 10.0M) or Sell Market.
You could also define Price like this:
type Price2 =
| Limit of Decimal option
| None
Whichever version will help you later do validation.

How to parse a decimal fraction into Rational in Haskell?

I've been participating in a programming contest and one of the problems' input data included a fractional number in a decimal format: 0.75 is one example.
Parsing that into Double is trivial (I can use read for that), but the loss of precision is painful. One needs to be very careful with Double comparisons (I wasn't), which seems redundant since one has Rational data type in Haskell.
When trying to use that, I've discovered that to read a Rational one has to provide a string in the following format: numerator % denominator, which I, obviously, do not have.
So, the question is:
What is the easiest way to parse a decimal representation of a fraction into Rational?
The number of external dependencies should be taken into consideration too, since I can't install additional libraries into the online judge.
The function you want is Numeric.readFloat:
Numeric Data.Ratio> fst . head $ readFloat "0.75" :: Rational
3 % 4
How about the following (GHCi session):
> :m + Data.Ratio
> approxRational (read "0.1" :: Double) 0.01
1 % 10
Of course you have to pick your epsilon appropriately.
Perhaps you'd get extra points in the contest for implementing it yourself:
import Data.Ratio ( (%) )
readRational :: String -> Rational
readRational input = read intPart % 1 + read fracPart % (10 ^ length fracPart)
where (intPart, fromDot) = span (/='.') input
fracPart = if null fromDot then "0" else tail fromDot

F# NumericLiteral: FromString method

Does anyone know if there is a way to automatically invoke the FromString method of a numeric literal in F#? I have already tried (and succeeded) with the methods FromOne, FromZero, etc but I have no idea how strings could be handled at compile time...
from page 51 of the F# language specification:
xxxx<suffix>
For xxxx = 0 -> NumericLiteral<suffix>.FromZero()
For xxxx = 1 -> NumericLiteral<suffix>.FromOne()
For xxxx in the Int32 range -> NumericLiteral<suffix>.FromInt32(xxxx)
For xxxx in the Int64 range -> NumericLiteral<suffix>.FromInt64(xxxx)
For other numbers -> NumericLiteral<suffix>.FromString("xxxx")
That means, only when the first 4 are not satisfied, FromString is called. Also, xxxx must be digits with signs, you cannot use other alphabeta set for xxxx.
I think it's intended for numbers bigger than Int64.MaxValue.

Resources