constant variable declaration in Haskell - haskell

To declare constant variables I can do following in Ruby
class COLOR
RED = 10
BLUE = 20
GREEM = 30
end
COLOR::RED returns 10, COLOR::BLUE returns 20, and so on. How do I accomplish that in Haskell?
I want to have a namespace name in front of my variable name. Maybe the example above is not a good example. For the case below, you can see including a namespace name will make a variable much easier to understand.
class BASEBALL_TEAM
GIANTS = 15
METS = 30
REDS = 45
...
end
BASEBALL_TEAM::GIANTS is much clear than GIANTS.
based on the comments below, it seems the only way I can accomplish it is by doing something like below:
module Color (Color) where
data Color = Red | Blue | Green deriving (Eq, Show, Ord, Bounded, Enum)
fromEnum' x = (fromEnum x) + 10
to get integer value of 10 for Color.Red, I have to write fromEnum Color.Red, the syntax is not very clean.

Untagged constants are bad. If you go with bunch of Int constants then you lose type-checking (think about possible values that Int -> whatever function takes as opposed to SomeConstType -> whatever) and possibly introduce bugs. You want a strong type instead:
data Colour = Red | Blue | Green deriving (Show, Eq, Enum)
Also, representing those values as integers is not really necessary in most cases. If you actually do need it, Enum typeclass provides toEnum and fromEnum.
As for namespaces: modules are namespaces in Haskell. Put your type in a module and then you can import it qualified and you'll have your prefix:
-- Colours.hs
module Colours (Colour) where
data Colour = ...
-- SomeOtherModule.hs
module SomeOtherModule where
import qualified Colours
foo = Colours.Red
That said, creating modules just for this one type with constants (or importing them qualified) is not really necessary, because you can easily trace things by their types.

Things are constant in Haskell by default, so
red = 10
blue = 20
green = 30
would be equivalent.
A more interesting question would be why you want to do this? There are likely better ways to accomplish what you want in Haskell. The answer by #CatPlusPlus shows a good way of doing this.
This seems like a very basic Haskell question, so I'll politely point you to Learn you a Haskell, which, in my opinion, is the best resource to get started with Haskell.
Another promising resource for learning Haskell is FP complete's School of Haskell, which is currently in beta, but I haven't tried it myself. This is a more interactive setting, where you can directly try things out in the browser.

Related

Non-uniform Distributions for Haskell data types

The random package contains a type class Uniform for uniformly distributed types.
This works for types like:
data Coin = Heads | Tails
But let's say I want to model a set of things with a non-uniform distribution, for example by adding the possibility of the coin landing on its side:
data Coin = Heads | Tails | Side
Now I could still implement Uniform with a non-uniform distribution in its implementation but that would be lying to the implicit rules of Uniform.
Do I have to just use a standalone function or is there some type class for the concept of an "actual" distribution?
This type class would be useful in the context of an RPG where you could have some types
data Rarity = Common | Rare
data DropType = Club | Sword
where the chances of getting a Rare and it being a Sword might be lower than the other values.
But the concept of drawing a value from the set of all values of that type is still the same for Rarity and DropType which is why this looks like a job for type classes to me.
One option is using random-fu, which offers a categorical distribution. A quick example:
import Data.Random
import Data.Random.Distribution.Categorical
import Data.Random.Sample
data Coin = Heads | Tails | Side deriving Show
-- set up distribution, weights don't have to sum to 1
coin :: Categorical Double Coin
coin = fromList [(0.5, Heads), (0.5, Tails), (0.001, Side)]
-- draw a single sample from the distribution
main = sample coin >>= print

Enums in Python: Building chess pieces

I am trying to build a simple chess board in Python 3 and I am a bit lost representing the pieces properly. I thought it would be a reasonable idea to defined values for every colour and piece like that:
from enum import Enum
class Piece(Enum):
"This class represents a piece and its colour"
Empty = 0
King = 1
Pawn = 2
Knight = 4
Bishop = 8
Rook = 16
Queen = 32
White = 64
Black = 128
Now I would like to represent a piece by concatenating the colour and the piece like that here:
squares = []
square[0] = Piece.White | Piece.Rook
Unfortunately, my IDE tells me that piece wouldn't have a member of type "Rook".
Is my way of using enums totally wrong? I am used to doing such stuff in other programming languages, but I am new to enums in Python. Is there any clever idea on how to fix that?
You're looking for a Flag enum. See the documentation for example usage, but your code as written should be fine if you just change Enum to Flag.

Representing a chessboard in Haskell

I'm trying to implement a function in Haskell that returns a list containing all possible moves for the player who's up. The function's only argument is a String composed of an actual state of the board (in Forsyth-Edwards Notation ) followed by the moving player(b/w).
Notation example : rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w (starting board state)
A move is transmitted as a string of the form [origin]-[destination]. The destination is always a position of the form [column][row], where the lower left square is called a1 and the upper right square is called h8. A move would be for example the move "b3-c4". (no castling/En-passant).
In Java I would use a 2d Array for the Board, but in Haskell I can't find a similar solution (I'm new to functional programming).
What would be a good way/data structure to represent the chess board in?
There are two primary options for storing a board state. The first is a 2D list of Maybe, where a piece would be represented as, e.g. Just $ Piece Black King and a blank square would be represented as Nothing. This optimizes determining if a square is occupied over listing where pieces are (which might be important if you plan to add rendering later):
type Board = Vector (Vector (Maybe Piece))
data Piece = Piece { color :: Color
, type :: PieceType }
The second option is to store a list of pieces and their locations. This implementation is faster to enumerate the locations of all pieces, but slower to check if there is a piece on a particular square:
type Pieces = [Placement]
type Placement = { position :: Position
, piece :: Piece }
data Position =
Pos { rank :: Int
, file :: Int }
deriving (Show, Eq)
data Piece =
Piece { color :: Color
, ptype :: PieceType }
deriving Show
EDIT: It's worth noting that with an 8x8 grid and a maximum of 32 pieces on the board, the performance hit either way is going to be minimal unless you're doing a lot of calculations.
Data.Vector, has constant time lookup by index.
A chessboard can be represented as a Vector (Vector (Maybe Piece)). To define Piece, see ADTs

Preventing operation on a value of custom data type

Let's say I create a Person type:
type Age = Int
type Height = Int
data Person = Person Age Height
This is all well, but I'd like to make sure that Age and Height cannot be added, because that makes no sense. I'd like a compile error when trying to do so.
In it's current form, this does not cause a compile error:
stupid (Person age height) = age + height
So I think about using newtype or even data for Age and Height:
newtype Age = Age Int
newtype Height = Height Int
data Person = Person Age Height
but still:
stupid (Person (Age age) (Height height)) = age + height
Is there a way of preventing age and height from being added? Or is what I'm asking for unreasonable?
By unwrapping the newtypes using the constructors Person and Height, you essentially instruct the compiler to forget the type distinction. That of course makes it legal to write age + height, but that's not to blame on the newtypes, like it's not to blame on the train driver if you smash the window, jump out and get injured!†
The way to prevent such incorrect operation is to not unwrap the newtypes. The following will cause an error, if Age and Height are newtypes:
stupid (Person age height) = age + height
...not just because age and height are different types, also because neither actually supports an addition operation (they aren't Num instances). Now that's fine, as long as you don't really need to perform any operations on these values.
Chances are however that at some point you will need to perform some operation on those values. This should not require the user to unwrap the actual newtype constructors.
For such physical quantities like age and height, there are a few options to do it type-safely:
Add VectorSpace instances. That will allow you to add one height to another, and scale heights by fractions, but not add a height to something entirely different.
import Data.AdditiveGroup
import Data.VectorSpace
instance Additive Height where
Height h₀ ^+^ Height h₁ = Height $ h₀+h₁
zeroV = Height 0
instance VectorSpace Height where
type Scalar Height = Double
μ *^ Height h = Height . round $ μ * fromIntegral h
This simple instance is mighty handy for some science use cases, though probably not that useful for your application.
Add meaningful unit-specific accessors. In modern Haskell, those would be lenses:
import Control.Lens
heightInCentimetres :: Lens' Height Int
heightInCentimetres = lens (\(Height h)->h) (\(Height _) h->Height h)
ageInYears :: Lens' Age Int
ageInYears = lens (\(Age a)->a) (\(Age _) a->Age a)
This way, if someone needs to work with an actual number of years of someone's age or modify it, they can do so, but they need to be explicit that these are years they're talking about. Of course, accessing the years and height as an integer number again makes it possible to circumvent the type distinction and intermingle ages with height, but this can hardly happen by accident.
Go all the way to a library for physical quantities.
import Data.Metrology.SI
type Height = Length
type Age = Time
This allows you to perform all kinds of physically legit operations while preventing nonsensical ones.
†Jumping out of a train is actually more dangerous. Rather like unsafeCoerce, which really instructs the compiler to throw all type-safety out of the window and can easily cause crashes or demons flying out of your nose.
This is actually a common pattern. Put the data type you want to protect into a module of its own:
module Quantities (
Age, Height, -- NOTE: constructors not exported
prettyHeight -- ...
) where
newtype Age = Age Int
newtype Height = Height Int
-- any operations that need to see the int, e.g.:
prettyHeight :: Height -> String
prettyHeight (Height h) = show h ++ "cm"
If you do not add an explicit export list to the module, everything will be exported, including the constructors Age and Height. In the above code, they are not exported, thus you can only access the Int values from within this module. All operations which actually have to work with the wrapped Int have to be in this module.
Now, import this module wherever you need it:
module Person where
import Quantities
data Person = Person Age Height
test (Height h) = () -- This will not compile, Height not in scope.
Any other module except Quantities can no longer deconstruct Height or Age.

How to model a 2D world in Haskell

I'm making a game. The game consists of an infinite plane. Units must be on a discrete square, so they can be located with a simple Location { x :: Int, y :: Int }
There might be many kinds of Units. Some might be creatures, and some are just objects, like a block of stone, or wood (think 2d minecraft there). Many will be empty (just grass or whatever).
How would you model this in Haskell? I've considered doing the below, but what about Object vs Creature? they might have different fields? Normalize them all on Unit?
data Unit = Unit { x :: Int, y :: Int, type :: String, ... many shared properties... }
I've also considered having a location type
data Location = Location { x :: Int, y :: Int, unit :: Unit }
-- or this
data Location = Location { x :: Int, y :: Int }
data Unit = Unit { unitFields... , location :: Location }
Do you have any ideas? In an OO language, I probably would have had Location or Unit inherit from the other, and made the specific types of Unit inherit from each other.
Another consideration is this will be sending lots of these objects over the wire, so I'll need to serialize them to JSON for use on the client, and don't want to write tons of parsing boilerplate.
Location is just a simple two-dimensional Point type.
I would advise against tying Units to the location they're in; just use a Map Location Unit to handle the map between positions on the grid and what (if anything) is present there.
As far as the specific types of Unit go, I would, at the very least, recommend factoring common fields out into a data type:
data UnitInfo = UnitInfo { ... }
data BlockType = Grass | Wood | ...
data Unit
= NPC UnitInfo AgentID
| Player UnitInfo PlayerID
| Block UnitInfo BlockType
or similar.
Generally, factor common things out into their own data-type, and keep data as simple and "isolated" as possible (i.e. move things like "what location is this unit at?" into separate structures associating the two, so that individual data-types are as "timeless", reusable and abstract as possible).
Having a String for the "type" of a Unit is a strong antipattern in Haskell; it generally indicates you're trying to implement dynamic typing or OOP structures with data types, which is a bad fit.
Your JSON requirement complicates things, but this FAQ entry shows a good example of how to idiomatically achieve this kind of genericity in Haskell with no String typing or fancy type-class hacks, using functions and data-types as the primary units of abstraction. Of course, the former causes you problems here; it's hard to serialise functions as JSON. However, you could maintain a map from an ADT representing a "type" of creature or block, etc., and its actual implementation:
-- records containing functions to describe arbitrary behaviour; see FAQ entry
data BlockOps = BlockOps { ... }
data CreatureOps = CreatureOps { ... }
data Block = Block { ... }
data Creature = Creature { ... }
data Unit = BlockUnit Block | CreatureUnit Creature
newtype GameField = GameField (Map Point Unit)
-- these types are sent over the network, and mapped *back* to the "rich" but
-- non-transferable structures describing their behaviour; of course, this means
-- that BlockOps and CreatureOps must contain a BlockType/CreatureType to map
-- them back to this representation
data BlockType = Grass | Wood | ...
data CreatureType = ...
blockTypes :: Map BlockType BlockOps
creatureTypes :: Map CreatureType CreatureOps
This lets you have all the extensibility and don't-repeat-yourself nature of typical OOP structures, while keeping the functional simplicity and allowing simple network transfer of game states.
Generally, you should avoid thinking in terms of inheritance and other OOP concepts; instead, try to think of dynamic behaviour in terms of functions and composition of simpler structures. A function is the most powerful tool in functional programming, hence the name, and can represent any complex pattern of behaviour. It's also best not to let requirements like network play influence your basic design; like the example above, it's almost always possible to layer these things on top of a design built for expressiveness and simplicity, rather than constraints like communication format.

Resources