packages feed

avwx 0.1.0.1 → 0.2.0.0

raw patch · 6 files changed

+1056/−900 lines, 6 filesdep +lensdep +parsersdep ~HTTPdep ~attoparsecPVP ok

version bump matches the API change (PVP)

Dependencies added: lens, parsers

Dependency ranges changed: HTTP, attoparsec

API changes (from Hackage documentation)

- Data.Aviation.WX: Cloud :: Cover -> Vertical -> CloudType -> Cloud
- Data.Aviation.WX: Runway :: Int -> Maybe Direction -> Runway
- Data.Aviation.WX: RunwayCondition :: Runway -> RwyCoverType -> Maybe Int -> Maybe Int -> RunwayBraking -> RunwayCondition
- Data.Aviation.WX: Visibility :: Distance -> (Maybe Direction) -> Visibility
- Data.Aviation.WX: [clouds] :: Weather -> [Cloud]
- Data.Aviation.WX: [date] :: Weather -> Date
- Data.Aviation.WX: [desc] :: WeatherPhenomenon -> Maybe WPDesc
- Data.Aviation.WX: [dewPoint] :: Weather -> Maybe Int
- Data.Aviation.WX: [direction] :: Wind -> WindDirection
- Data.Aviation.WX: [flags] :: Weather -> [Flag]
- Data.Aviation.WX: [from] :: WindDirection -> Int
- Data.Aviation.WX: [gusts] :: Wind -> Maybe Int
- Data.Aviation.WX: [intensity] :: WeatherPhenomenon -> WPIntensity
- Data.Aviation.WX: [mean] :: WindDirection -> Int
- Data.Aviation.WX: [obfus] :: WeatherPhenomenon -> Maybe WPObfuscation
- Data.Aviation.WX: [other] :: WeatherPhenomenon -> Maybe WPOther
- Data.Aviation.WX: [prec] :: WeatherPhenomenon -> Maybe WPPrecipitation
- Data.Aviation.WX: [pressure] :: Weather -> Maybe Pressure
- Data.Aviation.WX: [remark] :: Weather -> Maybe Text
- Data.Aviation.WX: [runwayDirection] :: Runway -> Maybe Direction
- Data.Aviation.WX: [runwayQFU] :: Runway -> Int
- Data.Aviation.WX: [runwaycond] :: Weather -> [RunwayCondition]
- Data.Aviation.WX: [runwayvis] :: Weather -> [(Runway, [Visibility], Maybe VisTrend)]
- Data.Aviation.WX: [rwclosedRunway] :: RunwayCondition -> Runway
- Data.Aviation.WX: [rwcondBrkCoeff] :: RunwayCondition -> RunwayBraking
- Data.Aviation.WX: [rwcondCoverHeight] :: RunwayCondition -> Maybe Int
- Data.Aviation.WX: [rwcondCover] :: RunwayCondition -> RwyCoverType
- Data.Aviation.WX: [rwcondRunway] :: RunwayCondition -> Runway
- Data.Aviation.WX: [rwcondSpread] :: RunwayCondition -> Maybe Int
- Data.Aviation.WX: [station] :: Weather -> Station
- Data.Aviation.WX: [temperature] :: Weather -> Maybe Int
- Data.Aviation.WX: [to] :: WindDirection -> Int
- Data.Aviation.WX: [trend] :: Weather -> Trend
- Data.Aviation.WX: [velocity] :: Wind -> Unit
- Data.Aviation.WX: [visibility] :: Weather -> [Visibility]
- Data.Aviation.WX: [wind] :: Weather -> Maybe Wind
- Data.Aviation.WX: [wx] :: Weather -> [WeatherPhenomenon]
- Data.Aviation.WX: data Station
- Data.Aviation.WX: parseWeather :: Text -> Either String Weather
- Data.Aviation.WX.Fetcher: type ICAOStationDesignator = String
+ Data.Aviation.WX: ObservedCloud :: Cover -> Vertical -> CloudType -> Cloud
+ Data.Aviation.WX: SpecificRunway :: Int -> Maybe Direction -> Runway
+ Data.Aviation.WX: SpecificRunwayCondition :: Runway -> RwyCoverType -> Maybe Int -> Maybe Int -> RunwayBraking -> RunwayCondition
+ Data.Aviation.WX: SpecificVisibility :: Distance -> (Maybe Direction) -> Visibility
+ Data.Aviation.WX: [_clouds] :: Weather -> [Cloud]
+ Data.Aviation.WX: [_dayOfMonth] :: Date -> Int
+ Data.Aviation.WX: [_desc] :: WeatherPhenomenon -> Maybe WPDesc
+ Data.Aviation.WX: [_dewPoint] :: Weather -> Maybe Int
+ Data.Aviation.WX: [_flags] :: Weather -> [Flag]
+ Data.Aviation.WX: [_gusts] :: Wind -> Maybe Int
+ Data.Aviation.WX: [_hour] :: Date -> Int
+ Data.Aviation.WX: [_intensity] :: WeatherPhenomenon -> WPIntensity
+ Data.Aviation.WX: [_maintenance] :: Weather -> Bool
+ Data.Aviation.WX: [_metardate] :: Weather -> Date
+ Data.Aviation.WX: [_metarpressure] :: Weather -> Maybe Pressure
+ Data.Aviation.WX: [_metarvisibility] :: Weather -> [Visibility]
+ Data.Aviation.WX: [_metarwind] :: Weather -> Maybe Wind
+ Data.Aviation.WX: [_minute] :: Date -> Int
+ Data.Aviation.WX: [_obfus] :: WeatherPhenomenon -> Maybe WPObfuscation
+ Data.Aviation.WX: [_other] :: WeatherPhenomenon -> Maybe WPOther
+ Data.Aviation.WX: [_prec] :: WeatherPhenomenon -> Maybe WPPrecipitation
+ Data.Aviation.WX: [_remark] :: Weather -> Maybe Text
+ Data.Aviation.WX: [_runwayDirection] :: Runway -> Maybe Direction
+ Data.Aviation.WX: [_runwayQFU] :: Runway -> Int
+ Data.Aviation.WX: [_runwaycond] :: Weather -> [RunwayCondition]
+ Data.Aviation.WX: [_runwayvis] :: Weather -> [(Runway, [Visibility], Maybe VisTrend)]
+ Data.Aviation.WX: [_rwclosedRunway] :: RunwayCondition -> Runway
+ Data.Aviation.WX: [_rwcondBrkCoeff] :: RunwayCondition -> RunwayBraking
+ Data.Aviation.WX: [_rwcondCoverHeight] :: RunwayCondition -> Maybe Int
+ Data.Aviation.WX: [_rwcondCover] :: RunwayCondition -> RwyCoverType
+ Data.Aviation.WX: [_rwcondRunway] :: RunwayCondition -> Runway
+ Data.Aviation.WX: [_rwcondSpread] :: RunwayCondition -> Maybe Int
+ Data.Aviation.WX: [_station] :: Weather -> Station
+ Data.Aviation.WX: [_temperature] :: Weather -> Maybe Int
+ Data.Aviation.WX: [_velocity] :: Wind -> Unit
+ Data.Aviation.WX: [_weathertrend] :: Weather -> Trend
+ Data.Aviation.WX: [_winddirection] :: Wind -> WindDirection
+ Data.Aviation.WX: [_windfrom] :: WindDirection -> Int
+ Data.Aviation.WX: [_windmean] :: WindDirection -> Int
+ Data.Aviation.WX: [_windto] :: WindDirection -> Int
+ Data.Aviation.WX: [_wx] :: Weather -> [WeatherPhenomenon]
+ Data.Aviation.WX: _ADClosed :: AsRunwayCondition r_anJf => Prism' r_anJf ()
+ Data.Aviation.WX: _AIRMET :: AsWeather r_alqw => Prism' r_alqw ()
+ Data.Aviation.WX: _AMD :: AsFlag r_alEI => Prism' r_alEI ()
+ Data.Aviation.WX: _ATIS :: AsWeather r_alqw => Prism' r_alqw ()
+ Data.Aviation.WX: _AUTO :: AsFlag r_alEI => Prism' r_alEI ()
+ Data.Aviation.WX: _AllRunways :: AsRunway r_annm => Prism' r_annm ()
+ Data.Aviation.WX: _Altimeter :: AsPressure r_am2C => Prism' r_am2C Int
+ Data.Aviation.WX: _Altitude :: AsVertical r_ao4o => Prism' r_ao4o Int
+ Data.Aviation.WX: _Altocumulus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Altostratus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _BECMG :: AsTrend r_alJv => Prism' r_alJv [Transition]
+ Data.Aviation.WX: _BKN :: AsCover r_aoGm => Prism' r_aoGm ()
+ Data.Aviation.WX: _Blowing :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _BrakingEffect :: AsRunwayBraking r_anOo => Prism' r_anOo Int
+ Data.Aviation.WX: _BrakingFriction :: AsRunwayBraking r_anOo => Prism' r_anOo Int
+ Data.Aviation.WX: _COR :: AsFlag r_alEI => Prism' r_alEI ()
+ Data.Aviation.WX: _Cirrostratus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Cirrus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Cloud :: AsCloud r_aopY => Prism' r_aopY Cloud
+ Data.Aviation.WX: _CloudType :: AsCloudType r_aotT => Prism' r_aotT CloudType
+ Data.Aviation.WX: _Cover :: AsCover r_aoGm => Prism' r_aoGm Cover
+ Data.Aviation.WX: _CoverNotSpecified :: AsCover r_aoGm => Prism' r_aoGm ()
+ Data.Aviation.WX: _Cumulonimbus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Cumulus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Degrees :: AsWindDirection r_aog4 => Prism' r_aog4 Int
+ Data.Aviation.WX: _Direction :: AsDirection r_an8a => Prism' r_an8a Direction
+ Data.Aviation.WX: _Distance :: AsDistance r_amW8 => Prism' r_amW8 Distance
+ Data.Aviation.WX: _Drizzle :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _Dust :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _DustOrSandwhirls :: AsWPOther r_amP9 => Prism' r_amP9 ()
+ Data.Aviation.WX: _Duststorm :: AsWPOther r_amP9 => Prism' r_amP9 ()
+ Data.Aviation.WX: _East :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _FEW :: AsCover r_aoGm => Prism' r_aoGm ()
+ Data.Aviation.WX: _FiftyMetresOrLess :: AsVisibility r_an29 => Prism' r_an29 ()
+ Data.Aviation.WX: _Flag :: AsFlag r_alEI => Prism' r_alEI Flag
+ Data.Aviation.WX: _FlightLevel :: AsVertical r_ao4o => Prism' r_ao4o Int
+ Data.Aviation.WX: _Fog :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _Freezing :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _GAMET :: AsWeather r_alqw => Prism' r_alqw ()
+ Data.Aviation.WX: _Hail :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _Haze :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _Heavy :: AsWPIntensity r_amdl => Prism' r_amdl ()
+ Data.Aviation.WX: _Height :: AsVertical r_ao4o => Prism' r_ao4o Int
+ Data.Aviation.WX: _IceCrystals :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _IcePellets :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _KM :: AsDistance r_amW8 => Prism' r_amW8 Int
+ Data.Aviation.WX: _KMH :: AsUnit r_aol5 => Prism' r_aol5 Int
+ Data.Aviation.WX: _Knots :: AsUnit r_aol5 => Prism' r_aol5 Int
+ Data.Aviation.WX: _Light :: AsWPIntensity r_amdl => Prism' r_amdl ()
+ Data.Aviation.WX: _LowDrifting :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _METAR :: AsWeather r_alqw => Prism' r_alqw (Date, Station, [Flag], Maybe Wind, [Visibility], [(Runway, [Visibility], Maybe VisTrend)], [RunwayCondition], [WeatherPhenomenon], [Cloud], Maybe Pressure, Maybe Int, Maybe Int, Trend, Maybe Text, Bool)
+ Data.Aviation.WX: _Metres :: AsDistance r_amW8 => Prism' r_amW8 Int
+ Data.Aviation.WX: _Miles :: AsUnit r_aol5 => Prism' r_aol5 Int
+ Data.Aviation.WX: _Mist :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _Moderate :: AsWPIntensity r_amdl => Prism' r_amdl ()
+ Data.Aviation.WX: _NM :: AsDistance r_amW8 => Prism' r_amW8 Int
+ Data.Aviation.WX: _NOSIG :: AsTrend r_alJv => Prism' r_alJv ()
+ Data.Aviation.WX: _NOTAVAIL :: AsTrend r_alJv => Prism' r_alJv ()
+ Data.Aviation.WX: _North :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _NorthEast :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _NorthWest :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _OVC :: AsCover r_aoGm => Prism' r_aoGm ()
+ Data.Aviation.WX: _ObservedCloud :: AsCloud r_aopY => Prism' r_aopY (Cover, Vertical, CloudType)
+ Data.Aviation.WX: _PROB :: AsTrend r_alJv => Prism' r_alJv (Int, Trend)
+ Data.Aviation.WX: _Patches :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _Pressure :: AsPressure r_am2C => Prism' r_am2C Pressure
+ Data.Aviation.WX: _QFE :: AsPressure r_am2C => Prism' r_am2C Int
+ Data.Aviation.WX: _QFF :: AsPressure r_am2C => Prism' r_am2C Int
+ Data.Aviation.WX: _QNH :: AsPressure r_am2C => Prism' r_am2C Int
+ Data.Aviation.WX: _RCTDry :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTDrySnow :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTFZRut :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTIce :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTMoist :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTRime :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTSlush :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTUnknown :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTWet :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RCTWetSnow :: AsRwyCoverType r_anrb => Prism' r_anrb ()
+ Data.Aviation.WX: _RWYCenter :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _RWYLeft :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _RWYRight :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _Rain :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _Recent :: AsWPIntensity r_amdl => Prism' r_amdl ()
+ Data.Aviation.WX: _Runway :: AsRunway r_annm => Prism' r_annm Runway
+ Data.Aviation.WX: _RunwayBraking :: AsRunwayBraking r_anOo => Prism' r_anOo RunwayBraking
+ Data.Aviation.WX: _RunwayCondition :: AsRunwayCondition r_anJf => Prism' r_anJf RunwayCondition
+ Data.Aviation.WX: _RwyClosed :: AsRunwayCondition r_anJf => Prism' r_anJf Runway
+ Data.Aviation.WX: _RwyCoverType :: AsRwyCoverType r_anrb => Prism' r_anrb RwyCoverType
+ Data.Aviation.WX: _SCT :: AsCover r_aoGm => Prism' r_aoGm ()
+ Data.Aviation.WX: _SIGMET :: AsWeather r_alqw => Prism' r_alqw ()
+ Data.Aviation.WX: _SM :: AsDistance r_amW8 => Prism' r_amW8 Int
+ Data.Aviation.WX: _SPECI :: AsWeather r_alqw => Prism' r_alqw ()
+ Data.Aviation.WX: _Sand :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _Sandstorm :: AsWPOther r_amP9 => Prism' r_amP9 ()
+ Data.Aviation.WX: _Shallow :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _ShowGrains :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _Shower :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _Smoke :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _Snow :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _SnowPellets :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _South :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _SouthEast :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _SouthWest :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _SpecificRunway :: AsRunway r_annm => Prism' r_annm (Int, Maybe Direction)
+ Data.Aviation.WX: _SpecificRunwayCondition :: AsRunwayCondition r_anJf => Prism' r_anJf (Runway, RwyCoverType, Maybe Int, Maybe Int, RunwayBraking)
+ Data.Aviation.WX: _SpecificVisibility :: AsVisibility r_an29 => Prism' r_an29 (Distance, Maybe Direction)
+ Data.Aviation.WX: _Squalls :: AsWPOther r_amP9 => Prism' r_amP9 ()
+ Data.Aviation.WX: _Stratocumulus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Stratus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _TAF :: AsWeather r_alqw => Prism' r_alqw ()
+ Data.Aviation.WX: _TEMPO :: AsTrend r_alJv => Prism' r_alJv [Transition]
+ Data.Aviation.WX: _TenOrMore :: AsVisibility r_an29 => Prism' r_an29 ()
+ Data.Aviation.WX: _Thunderstorm :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _Tornado :: AsWPOther r_amP9 => Prism' r_amP9 ()
+ Data.Aviation.WX: _ToweringCumulus :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _TransClouds :: AsTransition r_alQG => Prism' r_alQG [Cloud]
+ Data.Aviation.WX: _TransRunwayVis :: AsTransition r_alQG => Prism' r_alQG [(Runway, [Visibility], Maybe VisTrend)]
+ Data.Aviation.WX: _TransVis :: AsTransition r_alQG => Prism' r_alQG [Visibility]
+ Data.Aviation.WX: _TransWX :: AsTransition r_alQG => Prism' r_alQG [WeatherPhenomenon]
+ Data.Aviation.WX: _TransWind :: AsTransition r_alQG => Prism' r_alQG Wind
+ Data.Aviation.WX: _Transition :: AsTransition r_alQG => Prism' r_alQG Transition
+ Data.Aviation.WX: _Trend :: AsTrend r_alJv => Prism' r_alJv Trend
+ Data.Aviation.WX: _TwoOrMore :: AsVisibility r_an29 => Prism' r_an29 ()
+ Data.Aviation.WX: _Unclassified :: AsCloudType r_aotT => Prism' r_aotT ()
+ Data.Aviation.WX: _Unit :: AsUnit r_aol5 => Prism' r_aol5 Unit
+ Data.Aviation.WX: _UnknownPrecipitation :: AsWPPrecipitation r_amuB => Prism' r_amuB ()
+ Data.Aviation.WX: _VVis :: AsCloud r_aopY => Prism' r_aopY (Maybe Int)
+ Data.Aviation.WX: _Variable :: AsWindDirection r_aog4 => Prism' r_aog4 ()
+ Data.Aviation.WX: _Varying :: AsWindDirection r_aog4 => Prism' r_aog4 (Int, Int, Int)
+ Data.Aviation.WX: _VertNotSpec :: AsVertical r_ao4o => Prism' r_ao4o ()
+ Data.Aviation.WX: _Vertical :: AsVertical r_ao4o => Prism' r_ao4o Vertical
+ Data.Aviation.WX: _Vicinity :: AsWPIntensity r_amdl => Prism' r_amdl ()
+ Data.Aviation.WX: _VisTrend :: AsVisTrend r_alXP => Prism' r_alXP VisTrend
+ Data.Aviation.WX: _VisTrendDownward :: AsVisTrend r_alXP => Prism' r_alXP ()
+ Data.Aviation.WX: _VisTrendNoDistinctTendency :: AsVisTrend r_alXP => Prism' r_alXP ()
+ Data.Aviation.WX: _VisTrendUpward :: AsVisTrend r_alXP => Prism' r_alXP ()
+ Data.Aviation.WX: _Visibility :: AsVisibility r_an29 => Prism' r_an29 Visibility
+ Data.Aviation.WX: _VolcanicAsh :: AsWPObfuscation r_amFY => Prism' r_amFY ()
+ Data.Aviation.WX: _WPDesc :: AsWPDesc r_amkk => Prism' r_amkk WPDesc
+ Data.Aviation.WX: _WPIntensity :: AsWPIntensity r_amdl => Prism' r_amdl WPIntensity
+ Data.Aviation.WX: _WPObfuscation :: AsWPObfuscation r_amFY => Prism' r_amFY WPObfuscation
+ Data.Aviation.WX: _WPOther :: AsWPOther r_amP9 => Prism' r_amP9 WPOther
+ Data.Aviation.WX: _WPPrecipitation :: AsWPPrecipitation r_amuB => Prism' r_amuB WPPrecipitation
+ Data.Aviation.WX: _WXPartial :: AsWPDesc r_amkk => Prism' r_amkk ()
+ Data.Aviation.WX: _Weather :: AsWeather r_alqw => Prism' r_alqw Weather
+ Data.Aviation.WX: _West :: AsDirection r_an8a => Prism' r_an8a ()
+ Data.Aviation.WX: _WindDirection :: AsWindDirection r_aog4 => Prism' r_aog4 WindDirection
+ Data.Aviation.WX: class AsCloud r_aopY where _VVis = (.) _Cloud _VVis _ObservedCloud = (.) _Cloud _ObservedCloud
+ Data.Aviation.WX: class AsCloudType r_aotT where _Cumulonimbus = (.) _CloudType _Cumulonimbus _ToweringCumulus = (.) _CloudType _ToweringCumulus _Stratus = (.) _CloudType _Stratus _Cumulus = (.) _CloudType _Cumulus _Stratocumulus = (.) _CloudType _Stratocumulus _Altostratus = (.) _CloudType _Altostratus _Altocumulus = (.) _CloudType _Altocumulus _Cirrostratus = (.) _CloudType _Cirrostratus _Cirrus = (.) _CloudType _Cirrus _Unclassified = (.) _CloudType _Unclassified
+ Data.Aviation.WX: class AsCover r_aoGm where _FEW = (.) _Cover _FEW _SCT = (.) _Cover _SCT _BKN = (.) _Cover _BKN _OVC = (.) _Cover _OVC _CoverNotSpecified = (.) _Cover _CoverNotSpecified
+ Data.Aviation.WX: class AsDirection r_an8a where _North = (.) _Direction _North _South = (.) _Direction _South _East = (.) _Direction _East _West = (.) _Direction _West _NorthWest = (.) _Direction _NorthWest _NorthEast = (.) _Direction _NorthEast _SouthWest = (.) _Direction _SouthWest _SouthEast = (.) _Direction _SouthEast _RWYLeft = (.) _Direction _RWYLeft _RWYRight = (.) _Direction _RWYRight _RWYCenter = (.) _Direction _RWYCenter
+ Data.Aviation.WX: class AsDistance r_amW8 where _Metres = (.) _Distance _Metres _KM = (.) _Distance _KM _SM = (.) _Distance _SM _NM = (.) _Distance _NM
+ Data.Aviation.WX: class AsFlag r_alEI where _COR = (.) _Flag _COR _AMD = (.) _Flag _AMD _AUTO = (.) _Flag _AUTO
+ Data.Aviation.WX: class AsPressure r_am2C where _QNH = (.) _Pressure _QNH _Altimeter = (.) _Pressure _Altimeter _QFE = (.) _Pressure _QFE _QFF = (.) _Pressure _QFF
+ Data.Aviation.WX: class AsRunway r_annm where _AllRunways = (.) _Runway _AllRunways _SpecificRunway = (.) _Runway _SpecificRunway
+ Data.Aviation.WX: class AsRunwayBraking r_anOo where _BrakingFriction = (.) _RunwayBraking _BrakingFriction _BrakingEffect = (.) _RunwayBraking _BrakingEffect
+ Data.Aviation.WX: class AsRunwayCondition r_anJf where _SpecificRunwayCondition = (.) _RunwayCondition _SpecificRunwayCondition _RwyClosed = (.) _RunwayCondition _RwyClosed _ADClosed = (.) _RunwayCondition _ADClosed
+ Data.Aviation.WX: class AsRwyCoverType r_anrb where _RCTDry = (.) _RwyCoverType _RCTDry _RCTMoist = (.) _RwyCoverType _RCTMoist _RCTWet = (.) _RwyCoverType _RCTWet _RCTRime = (.) _RwyCoverType _RCTRime _RCTDrySnow = (.) _RwyCoverType _RCTDrySnow _RCTWetSnow = (.) _RwyCoverType _RCTWetSnow _RCTSlush = (.) _RwyCoverType _RCTSlush _RCTIce = (.) _RwyCoverType _RCTIce _RCTFZRut = (.) _RwyCoverType _RCTFZRut _RCTUnknown = (.) _RwyCoverType _RCTUnknown
+ Data.Aviation.WX: class AsTransition r_alQG where _TransWind = (.) _Transition _TransWind _TransVis = (.) _Transition _TransVis _TransRunwayVis = (.) _Transition _TransRunwayVis _TransWX = (.) _Transition _TransWX _TransClouds = (.) _Transition _TransClouds
+ Data.Aviation.WX: class AsTrend r_alJv where _BECMG = (.) _Trend _BECMG _TEMPO = (.) _Trend _TEMPO _PROB = (.) _Trend _PROB _NOSIG = (.) _Trend _NOSIG _NOTAVAIL = (.) _Trend _NOTAVAIL
+ Data.Aviation.WX: class AsUnit r_aol5 where _Knots = (.) _Unit _Knots _Miles = (.) _Unit _Miles _KMH = (.) _Unit _KMH
+ Data.Aviation.WX: class AsVertical r_ao4o where _Height = (.) _Vertical _Height _Altitude = (.) _Vertical _Altitude _FlightLevel = (.) _Vertical _FlightLevel _VertNotSpec = (.) _Vertical _VertNotSpec
+ Data.Aviation.WX: class AsVisTrend r_alXP where _VisTrendUpward = (.) _VisTrend _VisTrendUpward _VisTrendDownward = (.) _VisTrend _VisTrendDownward _VisTrendNoDistinctTendency = (.) _VisTrend _VisTrendNoDistinctTendency
+ Data.Aviation.WX: class AsVisibility r_an29 where _TenOrMore = (.) _Visibility _TenOrMore _FiftyMetresOrLess = (.) _Visibility _FiftyMetresOrLess _TwoOrMore = (.) _Visibility _TwoOrMore _SpecificVisibility = (.) _Visibility _SpecificVisibility
+ Data.Aviation.WX: class AsWPDesc r_amkk where _Shallow = (.) _WPDesc _Shallow _Patches = (.) _WPDesc _Patches _WXPartial = (.) _WPDesc _WXPartial _LowDrifting = (.) _WPDesc _LowDrifting _Blowing = (.) _WPDesc _Blowing _Shower = (.) _WPDesc _Shower _Thunderstorm = (.) _WPDesc _Thunderstorm _Freezing = (.) _WPDesc _Freezing
+ Data.Aviation.WX: class AsWPIntensity r_amdl where _Light = (.) _WPIntensity _Light _Moderate = (.) _WPIntensity _Moderate _Heavy = (.) _WPIntensity _Heavy _Vicinity = (.) _WPIntensity _Vicinity _Recent = (.) _WPIntensity _Recent
+ Data.Aviation.WX: class AsWPObfuscation r_amFY where _Mist = (.) _WPObfuscation _Mist _Fog = (.) _WPObfuscation _Fog _Smoke = (.) _WPObfuscation _Smoke _VolcanicAsh = (.) _WPObfuscation _VolcanicAsh _Dust = (.) _WPObfuscation _Dust _Sand = (.) _WPObfuscation _Sand _Haze = (.) _WPObfuscation _Haze
+ Data.Aviation.WX: class AsWPOther r_amP9 where _DustOrSandwhirls = (.) _WPOther _DustOrSandwhirls _Squalls = (.) _WPOther _Squalls _Tornado = (.) _WPOther _Tornado _Sandstorm = (.) _WPOther _Sandstorm _Duststorm = (.) _WPOther _Duststorm
+ Data.Aviation.WX: class AsWPPrecipitation r_amuB where _Drizzle = (.) _WPPrecipitation _Drizzle _Rain = (.) _WPPrecipitation _Rain _Snow = (.) _WPPrecipitation _Snow _ShowGrains = (.) _WPPrecipitation _ShowGrains _IceCrystals = (.) _WPPrecipitation _IceCrystals _IcePellets = (.) _WPPrecipitation _IcePellets _Hail = (.) _WPPrecipitation _Hail _SnowPellets = (.) _WPPrecipitation _SnowPellets _UnknownPrecipitation = (.) _WPPrecipitation _UnknownPrecipitation
+ Data.Aviation.WX: class AsWeather r_alqw where _METAR = (.) _Weather _METAR _ATIS = (.) _Weather _ATIS _SPECI = (.) _Weather _SPECI _TAF = (.) _Weather _TAF _AIRMET = (.) _Weather _AIRMET _SIGMET = (.) _Weather _SIGMET _GAMET = (.) _Weather _GAMET
+ Data.Aviation.WX: class AsWindDirection r_aog4 where _Variable = (.) _WindDirection _Variable _Degrees = (.) _WindDirection _Degrees _Varying = (.) _WindDirection _Varying
+ Data.Aviation.WX: class HasCloud c_aoph
+ Data.Aviation.WX: class HasCloudType c_aotc
+ Data.Aviation.WX: class HasCover c_aoFF
+ Data.Aviation.WX: class HasDate c_anRs where dayOfMonth = (.) date dayOfMonth hour = (.) date hour minute = (.) date minute
+ Data.Aviation.WX: class HasDirection c_an7t
+ Data.Aviation.WX: class HasDistance c_amVr
+ Data.Aviation.WX: class HasFlag c_alE1
+ Data.Aviation.WX: class HasPressure c_am1V
+ Data.Aviation.WX: class HasRunway c_anl2 where runwayDirection = (.) runway runwayDirection runwayQFU = (.) runway runwayQFU
+ Data.Aviation.WX: class HasRunwayBraking c_anNH
+ Data.Aviation.WX: class HasRunwayCondition c_anCX where rwclosedRunway = (.) runwayCondition rwclosedRunway rwcondBrkCoeff = (.) runwayCondition rwcondBrkCoeff rwcondCover = (.) runwayCondition rwcondCover rwcondCoverHeight = (.) runwayCondition rwcondCoverHeight rwcondRunway = (.) runwayCondition rwcondRunway rwcondSpread = (.) runwayCondition rwcondSpread
+ Data.Aviation.WX: class HasRwyCoverType c_anqu
+ Data.Aviation.WX: class HasTransition c_alPZ
+ Data.Aviation.WX: class HasTrend c_alIO
+ Data.Aviation.WX: class HasUnit c_aoko
+ Data.Aviation.WX: class HasVertical c_ao3H
+ Data.Aviation.WX: class HasVisTrend c_alX8
+ Data.Aviation.WX: class HasVisibility c_an1s
+ Data.Aviation.WX: class HasWPDesc c_amjD
+ Data.Aviation.WX: class HasWPIntensity c_amcE
+ Data.Aviation.WX: class HasWPObfuscation c_amFh
+ Data.Aviation.WX: class HasWPOther c_amOs
+ Data.Aviation.WX: class HasWPPrecipitation c_amtU
+ Data.Aviation.WX: class HasWeather c_al5T where clouds = (.) weather clouds dewPoint = (.) weather dewPoint flags = (.) weather flags maintenance = (.) weather maintenance metardate = (.) weather metardate metarpressure = (.) weather metarpressure metarvisibility = (.) weather metarvisibility metarwind = (.) weather metarwind remark = (.) weather remark runwaycond = (.) weather runwaycond runwayvis = (.) weather runwayvis station = (.) weather station temperature = (.) weather temperature weathertrend = (.) weather weathertrend wx = (.) weather wx
+ Data.Aviation.WX: class HasWeatherPhenomenon c_am7W where desc = (.) weatherPhenomenon desc intensity = (.) weatherPhenomenon intensity obfus = (.) weatherPhenomenon obfus other = (.) weatherPhenomenon other prec = (.) weatherPhenomenon prec
+ Data.Aviation.WX: class HasWind c_ao9G where gusts = (.) wind gusts velocity = (.) wind velocity winddirection = (.) wind winddirection
+ Data.Aviation.WX: class HasWindDirection c_aocG where windfrom = (.) windDirection windfrom windmean = (.) windDirection windmean windto = (.) windDirection windto
+ Data.Aviation.WX: cloud :: HasCloud c_aoph => Lens' c_aoph Cloud
+ Data.Aviation.WX: cloudType :: HasCloudType c_aotc => Lens' c_aotc CloudType
+ Data.Aviation.WX: clouds :: HasWeather c_al5T => Traversal' c_al5T [Cloud]
+ Data.Aviation.WX: cover :: HasCover c_aoFF => Lens' c_aoFF Cover
+ Data.Aviation.WX: date :: HasDate c_anRs => Lens' c_anRs Date
+ Data.Aviation.WX: dayOfMonth :: HasDate c_anRs => Lens' c_anRs Int
+ Data.Aviation.WX: desc :: HasWeatherPhenomenon c_am7W => Lens' c_am7W (Maybe WPDesc)
+ Data.Aviation.WX: dewPoint :: HasWeather c_al5T => Traversal' c_al5T (Maybe Int)
+ Data.Aviation.WX: direction :: HasDirection c_an7t => Lens' c_an7t Direction
+ Data.Aviation.WX: distance :: HasDistance c_amVr => Lens' c_amVr Distance
+ Data.Aviation.WX: flag :: HasFlag c_alE1 => Lens' c_alE1 Flag
+ Data.Aviation.WX: flags :: HasWeather c_al5T => Traversal' c_al5T [Flag]
+ Data.Aviation.WX: gusts :: HasWind c_ao9G => Lens' c_ao9G (Maybe Int)
+ Data.Aviation.WX: hour :: HasDate c_anRs => Lens' c_anRs Int
+ Data.Aviation.WX: instance Control.Lens.Wrapped.Wrapped Data.Aviation.WX.Station
+ Data.Aviation.WX: instance Data.Aviation.WX.AsCloud Data.Aviation.WX.Cloud
+ Data.Aviation.WX: instance Data.Aviation.WX.AsCloudType Data.Aviation.WX.CloudType
+ Data.Aviation.WX: instance Data.Aviation.WX.AsCover Data.Aviation.WX.Cover
+ Data.Aviation.WX: instance Data.Aviation.WX.AsDirection Data.Aviation.WX.Direction
+ Data.Aviation.WX: instance Data.Aviation.WX.AsDistance Data.Aviation.WX.Distance
+ Data.Aviation.WX: instance Data.Aviation.WX.AsFlag Data.Aviation.WX.Flag
+ Data.Aviation.WX: instance Data.Aviation.WX.AsPressure Data.Aviation.WX.Pressure
+ Data.Aviation.WX: instance Data.Aviation.WX.AsRunway Data.Aviation.WX.Runway
+ Data.Aviation.WX: instance Data.Aviation.WX.AsRunwayBraking Data.Aviation.WX.RunwayBraking
+ Data.Aviation.WX: instance Data.Aviation.WX.AsRunwayCondition Data.Aviation.WX.RunwayCondition
+ Data.Aviation.WX: instance Data.Aviation.WX.AsRwyCoverType Data.Aviation.WX.RwyCoverType
+ Data.Aviation.WX: instance Data.Aviation.WX.AsTransition Data.Aviation.WX.Transition
+ Data.Aviation.WX: instance Data.Aviation.WX.AsTrend Data.Aviation.WX.Trend
+ Data.Aviation.WX: instance Data.Aviation.WX.AsUnit Data.Aviation.WX.Unit
+ Data.Aviation.WX: instance Data.Aviation.WX.AsVertical Data.Aviation.WX.Vertical
+ Data.Aviation.WX: instance Data.Aviation.WX.AsVisTrend Data.Aviation.WX.VisTrend
+ Data.Aviation.WX: instance Data.Aviation.WX.AsVisibility Data.Aviation.WX.Visibility
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWPDesc Data.Aviation.WX.WPDesc
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWPIntensity Data.Aviation.WX.WPIntensity
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWPObfuscation Data.Aviation.WX.WPObfuscation
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWPOther Data.Aviation.WX.WPOther
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWPPrecipitation Data.Aviation.WX.WPPrecipitation
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWeather Data.Aviation.WX.Weather
+ Data.Aviation.WX: instance Data.Aviation.WX.AsWindDirection Data.Aviation.WX.WindDirection
+ Data.Aviation.WX: instance Data.Aviation.WX.HasCloud Data.Aviation.WX.Cloud
+ Data.Aviation.WX: instance Data.Aviation.WX.HasCloudType Data.Aviation.WX.CloudType
+ Data.Aviation.WX: instance Data.Aviation.WX.HasCover Data.Aviation.WX.Cover
+ Data.Aviation.WX: instance Data.Aviation.WX.HasDate Data.Aviation.WX.Date
+ Data.Aviation.WX: instance Data.Aviation.WX.HasDirection Data.Aviation.WX.Direction
+ Data.Aviation.WX: instance Data.Aviation.WX.HasDistance Data.Aviation.WX.Distance
+ Data.Aviation.WX: instance Data.Aviation.WX.HasFlag Data.Aviation.WX.Flag
+ Data.Aviation.WX: instance Data.Aviation.WX.HasPressure Data.Aviation.WX.Pressure
+ Data.Aviation.WX: instance Data.Aviation.WX.HasRunway Data.Aviation.WX.Runway
+ Data.Aviation.WX: instance Data.Aviation.WX.HasRunwayBraking Data.Aviation.WX.RunwayBraking
+ Data.Aviation.WX: instance Data.Aviation.WX.HasRunwayCondition Data.Aviation.WX.RunwayCondition
+ Data.Aviation.WX: instance Data.Aviation.WX.HasRwyCoverType Data.Aviation.WX.RwyCoverType
+ Data.Aviation.WX: instance Data.Aviation.WX.HasTransition Data.Aviation.WX.Transition
+ Data.Aviation.WX: instance Data.Aviation.WX.HasTrend Data.Aviation.WX.Trend
+ Data.Aviation.WX: instance Data.Aviation.WX.HasUnit Data.Aviation.WX.Unit
+ Data.Aviation.WX: instance Data.Aviation.WX.HasUnit Data.Aviation.WX.Wind
+ Data.Aviation.WX: instance Data.Aviation.WX.HasVertical Data.Aviation.WX.Vertical
+ Data.Aviation.WX: instance Data.Aviation.WX.HasVisTrend Data.Aviation.WX.VisTrend
+ Data.Aviation.WX: instance Data.Aviation.WX.HasVisibility Data.Aviation.WX.Visibility
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWPDesc Data.Aviation.WX.WPDesc
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWPIntensity Data.Aviation.WX.WPIntensity
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWPIntensity Data.Aviation.WX.WeatherPhenomenon
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWPObfuscation Data.Aviation.WX.WPObfuscation
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWPOther Data.Aviation.WX.WPOther
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWPPrecipitation Data.Aviation.WX.WPPrecipitation
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWeather Data.Aviation.WX.Weather
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWeatherPhenomenon Data.Aviation.WX.WeatherPhenomenon
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWind Data.Aviation.WX.Wind
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWindDirection Data.Aviation.WX.Wind
+ Data.Aviation.WX: instance Data.Aviation.WX.HasWindDirection Data.Aviation.WX.WindDirection
+ Data.Aviation.WX: instance Data.Aviation.WX.Station ~ t0 => Control.Lens.Wrapped.Rewrapped Data.Aviation.WX.Station t0
+ Data.Aviation.WX: intensity :: HasWeatherPhenomenon c_am7W => Lens' c_am7W WPIntensity
+ Data.Aviation.WX: maintenance :: HasWeather c_al5T => Traversal' c_al5T Bool
+ Data.Aviation.WX: metardate :: HasWeather c_al5T => Traversal' c_al5T Date
+ Data.Aviation.WX: metarpressure :: HasWeather c_al5T => Traversal' c_al5T (Maybe Pressure)
+ Data.Aviation.WX: metarvisibility :: HasWeather c_al5T => Traversal' c_al5T [Visibility]
+ Data.Aviation.WX: metarwind :: HasWeather c_al5T => Traversal' c_al5T (Maybe Wind)
+ Data.Aviation.WX: minute :: HasDate c_anRs => Lens' c_anRs Int
+ Data.Aviation.WX: newtype Station
+ Data.Aviation.WX: obfus :: HasWeatherPhenomenon c_am7W => Lens' c_am7W (Maybe WPObfuscation)
+ Data.Aviation.WX: other :: HasWeatherPhenomenon c_am7W => Lens' c_am7W (Maybe WPOther)
+ Data.Aviation.WX: prec :: HasWeatherPhenomenon c_am7W => Lens' c_am7W (Maybe WPPrecipitation)
+ Data.Aviation.WX: pressure :: HasPressure c_am1V => Lens' c_am1V Pressure
+ Data.Aviation.WX: remark :: HasWeather c_al5T => Traversal' c_al5T (Maybe Text)
+ Data.Aviation.WX: runway :: HasRunway c_anl2 => Lens' c_anl2 Runway
+ Data.Aviation.WX: runwayBraking :: HasRunwayBraking c_anNH => Lens' c_anNH RunwayBraking
+ Data.Aviation.WX: runwayCondition :: HasRunwayCondition c_anCX => Lens' c_anCX RunwayCondition
+ Data.Aviation.WX: runwayDirection :: HasRunway c_anl2 => Traversal' c_anl2 (Maybe Direction)
+ Data.Aviation.WX: runwayQFU :: HasRunway c_anl2 => Traversal' c_anl2 Int
+ Data.Aviation.WX: runwaycond :: HasWeather c_al5T => Traversal' c_al5T [RunwayCondition]
+ Data.Aviation.WX: runwayvis :: HasWeather c_al5T => Traversal' c_al5T [(Runway, [Visibility], Maybe VisTrend)]
+ Data.Aviation.WX: rwclosedRunway :: HasRunwayCondition c_anCX => Traversal' c_anCX Runway
+ Data.Aviation.WX: rwcondBrkCoeff :: HasRunwayCondition c_anCX => Traversal' c_anCX RunwayBraking
+ Data.Aviation.WX: rwcondCover :: HasRunwayCondition c_anCX => Traversal' c_anCX RwyCoverType
+ Data.Aviation.WX: rwcondCoverHeight :: HasRunwayCondition c_anCX => Traversal' c_anCX (Maybe Int)
+ Data.Aviation.WX: rwcondRunway :: HasRunwayCondition c_anCX => Traversal' c_anCX Runway
+ Data.Aviation.WX: rwcondSpread :: HasRunwayCondition c_anCX => Traversal' c_anCX (Maybe Int)
+ Data.Aviation.WX: rwyCoverType :: HasRwyCoverType c_anqu => Lens' c_anqu RwyCoverType
+ Data.Aviation.WX: station :: HasWeather c_al5T => Traversal' c_al5T Station
+ Data.Aviation.WX: temperature :: HasWeather c_al5T => Traversal' c_al5T (Maybe Int)
+ Data.Aviation.WX: transition :: HasTransition c_alPZ => Lens' c_alPZ Transition
+ Data.Aviation.WX: trend :: HasTrend c_alIO => Lens' c_alIO Trend
+ Data.Aviation.WX: unit :: HasUnit c_aoko => Lens' c_aoko Unit
+ Data.Aviation.WX: velocity :: HasWind c_ao9G => Lens' c_ao9G Unit
+ Data.Aviation.WX: vertical :: HasVertical c_ao3H => Lens' c_ao3H Vertical
+ Data.Aviation.WX: visTrend :: HasVisTrend c_alX8 => Lens' c_alX8 VisTrend
+ Data.Aviation.WX: visibility :: HasVisibility c_an1s => Lens' c_an1s Visibility
+ Data.Aviation.WX: wPDesc :: HasWPDesc c_amjD => Lens' c_amjD WPDesc
+ Data.Aviation.WX: wPIntensity :: HasWPIntensity c_amcE => Lens' c_amcE WPIntensity
+ Data.Aviation.WX: wPObfuscation :: HasWPObfuscation c_amFh => Lens' c_amFh WPObfuscation
+ Data.Aviation.WX: wPOther :: HasWPOther c_amOs => Lens' c_amOs WPOther
+ Data.Aviation.WX: wPPrecipitation :: HasWPPrecipitation c_amtU => Lens' c_amtU WPPrecipitation
+ Data.Aviation.WX: weather :: HasWeather c_al5T => Lens' c_al5T Weather
+ Data.Aviation.WX: weatherPhenomenon :: HasWeatherPhenomenon c_am7W => Lens' c_am7W WeatherPhenomenon
+ Data.Aviation.WX: weathertrend :: HasWeather c_al5T => Traversal' c_al5T Trend
+ Data.Aviation.WX: wind :: HasWind c_ao9G => Lens' c_ao9G Wind
+ Data.Aviation.WX: windDirection :: HasWindDirection c_aocG => Lens' c_aocG WindDirection
+ Data.Aviation.WX: winddirection :: HasWind c_ao9G => Lens' c_ao9G WindDirection
+ Data.Aviation.WX: windfrom :: HasWindDirection c_aocG => Traversal' c_aocG Int
+ Data.Aviation.WX: windmean :: HasWindDirection c_aocG => Traversal' c_aocG Int
+ Data.Aviation.WX: windto :: HasWindDirection c_aocG => Traversal' c_aocG Int
+ Data.Aviation.WX: wx :: HasWeather c_al5T => Traversal' c_al5T [WeatherPhenomenon]
+ Data.Aviation.WX.Fetcher: parseWeather :: Text -> Either String Weather
- Data.Aviation.WX: METAR :: Date -> Station -> [Flag] -> Maybe Wind -> [Visibility] -> [(Runway, [Visibility], Maybe VisTrend)] -> [RunwayCondition] -> [WeatherPhenomenon] -> [Cloud] -> Maybe Pressure -> Maybe Int -> Maybe Int -> Trend -> Maybe Text -> Weather
+ Data.Aviation.WX: METAR :: Date -> Station -> [Flag] -> Maybe Wind -> [Visibility] -> [(Runway, [Visibility], Maybe VisTrend)] -> [RunwayCondition] -> [WeatherPhenomenon] -> [Cloud] -> Maybe Pressure -> Maybe Int -> Maybe Int -> Trend -> Maybe Text -> Bool -> Weather
- Data.Aviation.WX: weatherParser :: Parser Weather
+ Data.Aviation.WX: weatherParser :: (Monad f, CharParsing f) => f Weather

Files

README.md view
@@ -1,4 +1,4 @@-[![Build Status](https://travis-ci.org/hce/avutils.svg?branch=master)](https://travis-ci.org/hce/avutils)+[![Build Status](https://travis-ci.org/hce/avwx.svg?branch=master)](https://travis-ci.org/hce/avwx)  avwx ====@@ -48,5 +48,6 @@       , dewPoint = Just 15       , trend = NOSIG       , remark = Nothing+      , maintenance = False           }     ...
avwx.cabal view
@@ -1,5 +1,5 @@ name:                avwx-version:             0.1.0.1+version:             0.2.0.0 synopsis:            Parse METAR weather reports description:         Parse METAR weather reports homepage:            https://github.com/hce/avwx@@ -17,12 +17,16 @@   hs-source-dirs:      src   exposed-modules:     Data.Aviation.WX                      , Data.Aviation.WX.Fetcher-  -- other-modules:       Data.Aviation.WX.Fetcher+     build-depends:       base >= 4.7 && < 5-                     , attoparsec-                     , HTTP+                     , lens >= 4.1 && < 5+                     , attoparsec >= 0.13 && < 1+                     , parsers >= 0.12 && < 1+                     , HTTP >= 4000 && < 5000                      , text >= 1.2.2.1 && < 1.3+                        default-language:    Haskell2010+  ghc-options:       -Wall  executable metar   hs-source-dirs:      app@@ -38,6 +42,7 @@   hs-source-dirs:      test   main-is:             Spec.hs   build-depends:       base+                     , attoparsec >= 0.13 && < 1                      , avwx                      , text   ghc-options:         -threaded -rtsopts -with-rtsopts=-N
changelog.md view
@@ -1,3 +1,16 @@+# 0.2.0.0++Many improvements by Tony Morris:++* Turn on GHC warnings+* The parser uses hackage/parsers library, so a user can choose the parser implementation e.g. attoparsec, parsec.+* A METAR optionally ends in $ or = instead of necessarily.+* Added a field to `Weather` for ending in $ (meaning the station requires maintenance).+* Added classy lenses to the data types.+* Updated the new noaa.gov METAR publication website for fetching.+* Moved parseWeather over to the `Fetcher` module so the parser does not ever import attoparsec.+* Make `Station` a newtype.+ # Jun 28 2016 -First release.+* First release.
src/Data/Aviation/WX.hs view
@@ -1,878 +1,1001 @@-{-# LANGUAGE OverloadedStrings #-}
--- |
--- Module: Data.Aviation.WX
--- Copyright: (C) 2014-2016, Hans-Christian Esperer
--- License: MIT
--- Maintainer: Hans-Christian Esperer <hc@hcesperer.org>
--- Stability: experimental
--- Portability: portable
---
--- Parse aviation weather reports. A qualified import is recommended.
-module Data.Aviation.WX
-    ( parseWeather
-    , weatherParser
-    , Weather(..)
-    , Date(..)
-    , Station(..)
-    , Flag(..)
-    , Wind(..)
-    , Visibility(..)
-    , Runway(..)
-    , VisTrend(..)
-    , RunwayCondition(..)
-    , WeatherPhenomenon(..)
-    , Cloud(..)
-    , Pressure(..)
-    , Trend(..)
-    , WPDesc(..)
-    , WPPrecipitation(..)
-    , WPObfuscation(..)
-    , WPOther(..)
-    , Distance(..)
-    , Direction(..)
-    , RwyCoverType(..)
-    , RunwayBraking(..)
-    , Vertical(..)
-    , WindDirection(..)
-    , Cover(..)
-    , CloudType(..)
-    , WPIntensity(..)
-    , Transition(..)
-    , Unit(..)
-    ) where
-
-import Control.Applicative
-import Control.Monad
-import Data.Attoparsec.Text
-import Data.Maybe
-import Data.Text (Text, pack)
-
--- | Aviation weather, currently only METARs are supported.
-data Weather
-    = -- | A METeorological Aerodrome Report
-      METAR
-    { -- | The observation date.
-      date        :: Date
-    , -- | The designation of the observing station.
-      station     :: Station
-    , -- | A remark about the reported observation.
-      flags       :: [Flag]
-    , -- | The observed wind.
-      wind        :: Maybe Wind
-    , -- | The observed visibility.
-      visibility  :: [Visibility]
-    , -- | The observed visibility for specific runways,
-      -- usually reported if the runway visibility significantly
-      -- differs from the general reported visibility.
-      runwayvis   :: [(Runway, [Visibility], Maybe VisTrend)]
-    , -- | Surface or close conditions of a specific runway.
-      runwaycond  :: [RunwayCondition]
-    , -- | Observed weather phenomena
-      wx          :: [WeatherPhenomenon]
-    , -- | Observed cloud layers
-      clouds      :: [Cloud]
-    , -- | Measured pressure
-      pressure    :: Maybe Pressure
-    , -- | Measured pressure
-      temperature :: Maybe Int
-    , -- | Determined dew point
-      dewPoint    :: Maybe Int
-    , -- | Expected changes within the next two hours
-      trend       :: Trend
-    , -- | RMK section (Additional parts of a METAR report that are not
-      -- part of the official METAR message but are commonly used
-      -- in various parts of the world; unparsed)
-      remark      :: Maybe Text }
-    | -- | An automatic terminal information service report
-      ATIS
-    | -- | A non-scheduled METAR
-      SPECI
-    | -- | A terminal aerodrome forecast
-      TAF
-    | -- | An aviation wx hazard message of moderate severity
-      AIRMET
-    | -- | A significant meteorological information message
-      SIGMET
-    | -- | A general aviation forecast message
-      GAMET
-    deriving (Eq, Show)
-
--- | A flag describing an aviation meteorological report
-data Flag
-    = -- | A message has been corrected after the beginning of
-      -- its original validity period
-      COR
-    | -- | A message has been corrected prior to its
-      -- original validity period
-      AMD
-    | -- | A message has been generated fully automatic
-      -- without a plausibility check by a human
-      AUTO
-    deriving (Eq, Show)
-
--- | The trend part of a METAR message specifies expected
--- changes in weather conditions within the next two hours.
--- A Trend/Transition part of a TAF message specified expected
--- changes in weather conditions within the specified range.
-data Trend
-    = -- | A transition that will start within the defined
-      -- time frame and be completed at the end of the defined
-      -- time frame
-      BECMG [Transition]
-    | -- | A transition that will start within the defined
-      -- time frame and be finished at the end of the defined
-      -- time frame
-      TEMPO [Transition]
-    | -- | A probability specification.
-      -- As one of my FIs (ex-atc at EDDF) used to put it:
-      -- 30% means "I'm quite sure it won't happen but will still
-      -- put it in here, in case it does after all."
-      -- 40% means "I'm certain it will happen but will still
-      -- put it with 40%, in case it does not happen after all."
-      PROB Int Trend
-    | -- | NOSIG is only applicable to METARs. It means that
-      -- no significant changes are expected within the next
-      -- two hours.
-      NOSIG
-    | -- | NOTAVAIL is only applicable to METARs. It means that
-      -- the METAR message in question does not contain a TREND
-      -- section.
-      NOTAVAIL
-    deriving (Eq, Show)
-
--- | A transition in weather conditions.
--- A transition can either be temporary or permanent;
--- this will be encoded in the container structure.
-data Transition
-    = -- | A change of wind strength or direction
-      TransWind Wind
-    | -- | A change of visibility
-      TransVis [Visibility]
-    | -- | A change of visibility for a specific runway
-      TransRunwayVis [(Runway, [Visibility], Maybe VisTrend)]
-    | -- | A change of weather phenomenon
-      TransWX [WeatherPhenomenon]
-    | -- | A change of ceiling or cloud layers
-      TransClouds [Cloud]
-    deriving (Eq, Show)
-
--- | A visibility trend specifically for runway conditions
-data VisTrend
-    = -- | Visibility will improve (maybe do wait a bit)
-      VisTrendUpward
-    | -- | Visibility will deteriorate (still, don't rush
-      -- the take off and use proper phraseology at all times)
-      VisTrendDownward
-    | -- | No expected change in runway visibility conditions
-      VisTrendNoDistinctTendency
-    deriving (Eq, Show)
-
--- | A pressure value. This is intentionally coded
--- individually and not converted to a specific reference.
-data Pressure
-    = -- | The QNH value in hectopascals. QNH is the current
-      -- pressure at sea level, corrected for pressure and
-      -- temperature changes at the station level.
-      QNH Int
-    | -- | The same as QNH, only in inches
-      -- (Do you know the old joke?:
-      --   * ATC: Liner 1723 descend to 3,000ft, the QNH is 1013mb.
-      --   * Liner 1723: Uh, approach, can we have that in inches please?
-      --   * ATC: Liner 1723 descend to 36,000 inches, the QNH is 1013mb.
-      Altimeter Int
-    | -- | The current pressure at station level in hectopascals.
-      QFE Int
-    | -- | The current pressure at sea level in hectopascals.
-      QFF Int
-    deriving (Eq, Show)
-
--- | A weather phenomenon.
--- This can be an observed phenomenon in the case of METARs or an
--- expected phenomenon in the case of TAFs.
-data WeatherPhenomenon
-    = Phenomenon
-    { -- | The intensity of the phenomenon.
-      intensity :: WPIntensity
-    , -- | The description of the weather phenomenon.
-      desc      :: Maybe WPDesc
-    , -- | The precipitation type of the weather phenomenon.
-      prec      :: Maybe WPPrecipitation
-    , -- | The effects of the phenomenon on the visibility
-      obfus     :: Maybe WPObfuscation
-    , -- | Other details about the phenomenon.
-      other     :: Maybe WPOther }
-    deriving (Eq, Show)
-
--- | The intensity of an observed or expected weather phenomenon.
-data WPIntensity
-    = -- | Light
-      Light
-    | -- | Moderate
-      Moderate
-    | -- | Heavy
-      Heavy
-    | -- | Only applicable to METARs. The weather phenomenon was
-      -- observed in the vicinity of the observed area, not within
-      -- the observed area itself.
-      Vicinity
-    | -- | Only applicable to METARs. The weather phenomenon was
-      -- recently observed in the past, but was not observed at
-      -- the time the report was issued.
-      Recent
-    deriving (Enum, Eq, Show)
-
--- | The description of a weather phenomenon.
-data WPDesc
-    = -- | Shallow.
-      Shallow
-    | -- | Patches.
-      Patches
-    | -- | Partial.
-      WXPartial
-    | -- | Low, drifting.
-      LowDrifting
-    | -- | Blowing.
-      Blowing
-    | -- | Shower.
-      Shower
-    | -- | Thunderstorm.
-      Thunderstorm
-    | -- | Freezing.
-      Freezing
-    deriving (Enum, Eq, Ord, Show)
-
--- | The type of the precipitation
-data WPPrecipitation
-    = -- | Drizzle.
-      Drizzle
-    | -- | Rain.
-      Rain
-    | -- | Snow.
-      Snow
-    | -- | Snow grains.
-      ShowGrains
-    | -- | Ice crystals.
-      IceCrystals
-    | -- | Ice pellets.
-      IcePellets
-    | -- | Hail.
-      Hail
-    | -- | Snow pellets.
-      SnowPellets
-    | -- | Unknown type of precipitation.
-      UnknownPrecipitation
-    deriving (Enum, Eq, Ord, Show)
-
--- | Effects on the visibility by a weather phenomenon
-data WPObfuscation
-    = -- | Mist. Visibility impaired but still greater than 1000m
-      Mist
-    | -- | Fog. Visibility less than 1000m.
-      Fog
-    | -- | Smoke.
-      Smoke
-    | -- | Volcanic ash.
-      VolcanicAsh
-    | -- | Dust.
-      Dust
-    | -- | Sand.
-      Sand
-    | -- | Haze.
-      Haze
-    deriving (Enum, Eq, Ord, Show)
-
--- | Other important information about a weather phenomenon.
-data WPOther
-    = -- | Dust or sand whirls.
-      DustOrSandwhirls
-    | -- | Squalls.
-      Squalls
-    | -- | Tornado.
-      Tornado
-    | -- | Sand storm.
-      Sandstorm
-    | -- | Dust storm.
-      Duststorm
-    deriving (Enum, Eq, Ord, Show)
-
--- | The Distance.
-data Distance
-    = -- | The distance in metres.
-      Metres Int
-    | -- | The distance in km.
-      KM Int
-    | -- | The distance in statute miles.
-      SM Int
-    | -- | The distance in nautical miles.
-      NM Int
-    deriving (Eq, Show)
-
--- | Vertical visibility.
-data Visibility
-    = -- | Ten kilometres or more.
-      TenOrMore
-    | -- | Fifty metres or less.
-      FiftyMetresOrLess
-    | -- | Two kilometres or more.
-      TwoOrMore
-    | -- | A specific visibility.
-      Visibility Distance (Maybe Direction)
-    deriving (Eq, Show)
-
--- | Directions.
-data Direction
-    = -- | North.
-      North
-    | -- | South.
-      South
-    | -- | East.
-      East
-    | -- | West.
-      West
-    | -- | Northwest.
-      NorthWest
-    | -- | Northeast.
-      NorthEast
-    | -- | Southwest.
-      SouthWest
-    | -- | Southeast.
-      SouthEast
-    | -- | Left runway for runways of the same QFU
-      -- (part of the runway designator)
-      RWYLeft
-    | -- | Right runway for runways of the same QFU
-      -- (part of the runway designator)
-      RWYRight
-    | -- | Centre runway for runways of the same QFU
-      -- (part of the runway designator)
-      RWYCenter
-    deriving (Eq, Show)
-
--- | Runway specification.
-data Runway
-    = -- | All runways.
-      AllRunways
-    | -- | A specific runway.
-      Runway
-    { -- | The runway's magnetic orientation, divided by ten and rounded.
-      runwayQFU                 :: Int
-    , -- | For multiple runways with the same QFU, a left, right or centre
-      -- selector is added.
-      runwayDirection           :: Maybe Direction }
-    deriving (Eq, Show)
-
--- | The runway contamination type.
-data RwyCoverType
-    = -- | The runway is not contaminated.
-      RCTDry
-    | -- | The runway is moist.
-      RCTMoist
-    | -- | The runway is wet.
-      RCTWet
-    | -- | The runway is convered with rime.
-      RCTRime
-    | -- | The runway is covered with dry snow.
-      RCTDrySnow
-    | -- | The runway is covered with wet snow.
-      RCTWetSnow
-    | -- | The runway is covered with slush.
-      RCTSlush
-    | -- | The runway is covered with ice.
-      RCTIce
-    | -- | The runway is covered with frozen ruts or ridges.
-      RCTFZRut
-    | -- | The runway contamination type is unknown.
-      RCTUnknown
-    deriving (Eq, Show, Enum)
-
--- | Runway conditions.
-data RunwayCondition
-    = -- | Specific runway conditions exist.
-      RunwayCondition
-    { -- | The runway for which specific conditions
-      -- have been observed.
-      rwcondRunway :: Runway
-    , -- | Whether and how the runway is contamindated.
-      rwcondCover  :: RwyCoverType
-    , -- | The extent of the contamination in percent.
-      rwcondSpread :: Maybe Int
-    , -- | The height of the contamination in millimetres.
-      rwcondCoverHeight :: Maybe Int
-    , -- | The friction coefficient or braking action value.
-      rwcondBrkCoeff :: RunwayBraking }
-    | -- | The runway is closed.
-      RwyClosed
-    { -- | The runway that is closed.
-      rwclosedRunway :: Runway }
-    | -- | The whole aerodrome is closed.
-      ADClosed
-    deriving (Eq, Show)
-
--- | The measured brake efficiency of a specific runway.
-data RunwayBraking
-    = -- | The friction coefficient.
-      BrakingFriction Int
-    | -- | The braking coefficient.
-      BrakingEffect Int
-    deriving (Eq, Show)
-
--- | An obersvation date.
-data Date
-    = Date Int Int Int
-    deriving (Eq, Show)
-
--- | An aeronautical weather station designator.
-data Station
-    = -- | The station as identified by its aerodrome's
-      -- ICAO code.
-      ICAO Text
-    deriving (Eq, Show)
-
--- | A vertical position specification.
-data Vertical
-    = -- | A vertical position with reference to the ground
-      -- in feet.
-      Height Int
-    | -- | A vertical position with reference to the mean
-      -- sea level/QNH in feet.
-      Altitude Int
-    | -- | A pressure altitude with reference to the
-      -- standard QNH of 1013 hectopascals in hundrets of feet.
-      FlightLevel Int
-    | -- | Vertical position is not specified.
-      VertNotSpec
-    deriving (Eq, Show)
-
--- | Wind information.
-data Wind
-    = Wind
-    { -- | The direction the wind is blowing from.
-      direction :: WindDirection
-    , -- | The wind speed.
-      velocity  :: Unit
-    , -- | The strength of the observed gusts, if any.
-      gusts     :: Maybe Int
-    } deriving (Eq, Show)
-
--- | The direction the wind is blowing from.
-data WindDirection
-    = -- | The wind is blowing in equal or almost equal
-      -- strength from a wide variety of directions.
-      Variable
-    | -- | The wind is blowing from the specified direction.
-      -- Directions can be given with reference to true or
-      -- magnetic north, depending on the type of weather
-      -- observation/forecast message.
-      Degrees Int
-    | -- | The wind is blowing from a specific direction
-      -- range.
-      Varying
-    { -- | The mean direction the wind is blowing from.
-      mean :: Int
-    , -- | The minimum direction the wind is blowing from.
-      from :: Int
-    , -- | The maximum direction the wind is blowing from.
-      to   :: Int
-    } deriving (Eq, Show)
-     
-
--- | A speed unit.
-data Unit
-    = -- | Nautical miles per hour
-      Knots Int
-    | -- | Statute miles per hour
-      Miles Int
-    | -- | Kilometres per hour
-      KMH Int
-    deriving (Eq, Show)
-
--- | A cloud specification.
-data Cloud
-    = -- | No specific clouds could be observed, because
-      -- the (given) ground visibility was too low or because
-      -- the ground is covered in clouds.
-      VVis (Maybe Int)
-    | -- | Clouds were observed.
-      Cloud Cover Vertical CloudType
-    deriving (Eq, Show)
-
--- | The type of cloud.
-data CloudType
-    = -- | A cumulonimbus cloud.
-      Cumulonimbus
-    | -- | A developing cb cloud.
-      ToweringCumulus
-    | -- | A stratus cloud.
-      Stratus
-    | -- | A cumulus cloud.
-      Cumulus
-    | -- | A stratocumulus cloud.
-      Stratocumulus
-    | -- | An altostratus cloud.
-      Altostratus
-    | -- | An altocumulus cloud.
-      Altocumulus
-    | -- | A cirrostratus cloud.
-      Cirrostratus
-    | -- | A cirrus cloud.
-      Cirrus
-    | -- | An unclassified cloud.
-      Unclassified
-    deriving (Enum, Eq, Show)
-
--- | The area that is covered.
-data Cover
-    = -- | 1-2 eights are covered.
-      FEW
-    | -- | 3-4 eights are covered.
-      SCT
-    | -- | 5-7 eights are covered.
-      BKN
-    | -- | More than 7 eights are covered.
-      OVC
-    | -- | Cover not specified
-      CoverNotSpecified
-    deriving (Enum, Eq, Ord, Show)
-
-stationParser :: Parser Station
-stationParser = ICAO <$> Data.Attoparsec.Text.take 4
-
-dateParser :: Parser Date
-dateParser = Date <$> twin <*> twin <*> (twin <* "Z")
-    where twin = (\a b -> read [a, b]) <$> digit <*> digit
-
-variableWindParser :: WindDirection -> Parser WindDirection
-variableWindParser (Degrees meanWind) = try $ do
-    dir1 <- (\a b c -> read [a, b, c]) <$> digit <*> digit <*> digit
-    _ <- char 'V'
-    dir2 <- (\a b c -> read [a, b, c]) <$> digit <*> digit <*> digit
-    return $ Varying meanWind dir1 dir2
-variableWindParser _ = fail "Erroneous parameters"
-
-windParser :: Parser Wind
-windParser = do
-    dir <- choice [readwinddir, variablewind]
-    str <- readwindstr
-    gustsies <- option Nothing readgusts
-    unit <- readunit
-    dir2 <- option dir $ char ' ' >> variableWindParser dir
-    return $ Wind dir2 (unit str) gustsies
-    where
-        variablewind = "VRB" `means` Variable
-        readwinddir = (\a b c -> Degrees . read $ [a, b, c]) <$> digit <*> digit <*> digit
-        readwindstr = (\a b -> read [a, b]) <$> digit <*> digit
-        readunit = choice [ "KT" `means` Knots
-                          , "MPH" `means` Miles
-                          , "KM" `means` KMH]
-        readgusts = (\_ b c -> Just . read $ [b, c]) <$> char 'G' <*> digit <*> digit
-
-pressureParser :: Parser Pressure
-pressureParser = choice [qnh, mmhg]
-    where
-      qnh = (\_ a b c d -> QNH $ read [a, b, c, d]) <$> char 'Q' <*> digit <*> digit <*> digit <*> digit
-      mmhg = (\_ a b c d -> Altimeter $ read [a, b, c, d]) <$> char 'A' <*> digit <*> digit <*> digit <*> digit
-
-wxParser :: Parser WeatherPhenomenon
-wxParser = do
-    skipSpace
-    intsy <- intensityParser
-    dsc <- perhaps descParser
-    prc <- perhaps precipitationParser
-    obfs <- perhaps obfuscationParser
-    othr <- perhaps otherParser
-    when ( (== 0) . Prelude.length . Prelude.filter not $
-        [ isNothing dsc, isNothing prc
-        , isNothing obfs, isNothing othr ] ) $ fail ""
-    return $ Phenomenon intsy dsc prc obfs othr
-
-perhaps :: Parser a -> Parser (Maybe a)
-perhaps parser = option Nothing $ Just <$> parser
-
-perhaps_ :: Parser a -> Parser ()
-perhaps_ parser = void $ perhaps parser
-
-callsfor :: Text -> Parser a -> Parser a
-a `callsfor` b = string a >> b
-
-means :: Text -> a -> Parser a
-a `means` b = string a >> return b
-
-means' :: Text -> a -> Parser a
-a `means'` b = try $ skipSpace >> string a >> skipSpace >> return b
-
-descParser :: Parser WPDesc
-descParser = choice
-    [ "MI" `means` Shallow
-    , "BC" `means` Patches
-    , "PR" `means` WXPartial
-    , "DR" `means` LowDrifting
-    , "BL" `means` Blowing
-    , "SH" `means` Shower
-    , "TS" `means` Thunderstorm
-    , "FZ" `means` Freezing ]
-
-precipitationParser :: Parser WPPrecipitation
-precipitationParser = choice
-    [ "DZ" `means` Drizzle
-    , "RA" `means` Rain
-    , "SN" `means` Snow
-    , "SG" `means` ShowGrains
-    , "IC" `means` IceCrystals
-    , "PL" `means` IcePellets
-    , "GR" `means` Hail
-    , "GS" `means` SnowPellets
-    , "UP" `means` UnknownPrecipitation ]
-
-obfuscationParser :: Parser WPObfuscation
-obfuscationParser = choice
-    [ "BR" `means` Mist
-    , "FG" `means` Fog
-    , "FU" `means` Smoke
-    , "VA" `means` VolcanicAsh
-    , "DU" `means` Dust
-    , "SA" `means` Sand
-    , "HZ" `means` Haze ]
-
-otherParser :: Parser WPOther
-otherParser = choice
-    [ "PO" `means` DustOrSandwhirls
-    , "SQ" `means` Squalls
-    , "FC" `means` Tornado
-    , "SS" `means` Sandstorm
-    , "DS" `means` Duststorm ]
-
-intensityParser :: Parser WPIntensity
-intensityParser = option Moderate $ choice
-    [ char '-' >> return Light
-    , char '+' >> return Heavy
-    , "VC" `means` Vicinity
-    , "RE" `means` Recent ]
-
-visibilityParser :: Parser Visibility
-visibilityParser = skipSpace >> choice [ tenormore, arb, arb1, metres ]
-    where
-        tenormore = string "9999" >> return TenOrMore
-        metres = (\a b c d dir -> Visibility (visunit $ read [a,b,c,d]) dir) <$> digit <*> digit <*> digit <*> digit <*> directionParser
-        visunit :: Int -> Distance
-        visunit n = if n > 5000
-            then KM (n `quot` 1000)
-            else Metres n
-        arb  = (\a b unit -> Visibility (unit $ read [a,b])) <$> digit <*> digit <*> distanceUnitParser <*> directionParser
-        arb1 = (\a unit -> Visibility (unit $ read ['0', a])) <$> digit <*> distanceUnitParser <*> directionParser
-
-directionParser :: Parser (Maybe Direction)
-directionParser = Nothing `option` (Just <$> choice
-    [ "NE" `means` NorthEast, "NW" `means` NorthWest
-    , "SE" `means` SouthEast, "SW" `means` SouthWest
-    , "N" `means` North, "S" `means` South
-    , "E" `means` East, "W" `means` West ])
-
-distanceUnitParser :: Parser (Int -> Distance)
-distanceUnitParser = choice
-    [ "KM" `means` KM
-    , "SM" `means` SM
-    , "NM" `means` NM ]
-
-cloudParser :: Parser [Cloud]
-cloudParser = choice [(:[]) <$> vvisParser, nsc, cavok, clr, sepBy1' clds (char ' ')]
-    where
-        clds = do
-            perhaps_ space
-            intsy <- cloudIntensityParser
-            height <- choice
-                [ "///" `means` VertNotSpec
-                , (\a b c -> Height $ (* 100) $ read [a, b, c]) <$> digit <*> digit <*> digit ]
-
-            cloudType <- cloudTypeParser
-            return $ Cloud intsy height cloudType
-        cavok = skipSpace >> "CAVOK" `means` []
-        nsc = skipSpace >> "NSC" `means` []
-        clr = skipSpace >> "CLR" `means` []
-
-vvisParser :: Parser Cloud
-vvisParser = do
-    _ <- string "VV"
-    choice
-        [ "///" `means` VVis Nothing
-        , (\a b c -> VVis . Just . read $ [a,b,c]) <$> digit <*> digit <*> digit ]
-
-cloudIntensityParser :: Parser Cover
-cloudIntensityParser = choice
-    [ "FEW" `means` FEW
-    , "SCT" `means` SCT
-    , "BKN" `means` BKN
-    , "OVC" `means` OVC
-    , "///" `means` CoverNotSpecified ]
-
-cloudTypeParser :: Parser CloudType
-cloudTypeParser = option Unclassified $ choice
-    [ "CB" `means` Cumulonimbus
-    , "TCU" `means` ToweringCumulus
-    , "ST" `means` Stratus
-    , "CU" `means` Cumulus
-    , "SC" `means` Stratocumulus
-    , "AS" `means` Altostratus
-    , "AC" `means` Altocumulus
-    , "CS" `means` Cirrostratus
-    , "CI" `means` Cirrus
-    , "///" `means` Unclassified]
-
-perhapsMinus :: Parser String
-perhapsMinus = "" `option` (char 'M' >> return "-")
-
-tdParser :: Parser (Int, Int)
-tdParser = do
-    tmpr <- (\pm a b -> read (pm ++ [a, b]) :: Int) <$> perhapsMinus <*> digit <*> digit
-    _ <- char '/'
-    dewpoint <- (\pm a b -> read (pm ++ [a, b]) :: Int) <$> perhapsMinus <*> digit <*> digit
-    return (tmpr, dewpoint)
-
-flagsParser :: Parser [Flag]
-flagsParser = many' $ choice
-    [ "COR" `means'` COR
-    , "AMD" `means'` AMD
-    , "AUTO" `means'` AUTO ]
-
-runwayvisParser :: Parser (Runway, [Visibility], Maybe VisTrend)
-runwayvisParser = do
-    runway <- runwayDesignationParser
-    _ <- char '/'
-    vis <- parseRwyVis
-    vistrend <- Nothing `option` (Just <$> choice
-        [ "D" `means` VisTrendDownward
-        , "N" `means` VisTrendNoDistinctTendency
-        , "U" `means` VisTrendUpward ] )
-    return (runway, vis, vistrend)
-    where
-        parseRwyVis :: Parser [Visibility]
-        parseRwyVis = do
-            worstvis <- Nothing `option` (Just <$> choice visspec <* "V")
-            vis <- Just <$> choice visspec
-            return $ catMaybes [worstvis, vis]
-                        
-        visspec =
-            [ "M0050" `means` FiftyMetresOrLess
-            , "P2000" `means` TwoOrMore
-            , fourDigits >>= \a -> return $ Visibility (Metres a) Nothing
-            , trieDigits >>= \a -> return $ Visibility (Metres a) Nothing ]
-                        
-runwayconditionParser :: Parser RunwayCondition
-runwayconditionParser = do
-    runway <- runwayDesignationParser
-    _ <- char '/'
-    choice
-        [ "SNOCLO" `means` ADClosed
-        , rwycond runway ]
-
-    where
-        rwycond runway = do
-            cover <- RCTUnknown `option` ((toEnum . read . (:[])) <$> digit)
-            spread <- choice
-                [ char '/' >> return Nothing
-                , (Just . read . (:[])) <$> digit ]
-            spreadheight <- choice
-                [ string "//" >> return Nothing
-                , Just <$> tuhDigits ]
-            rkorbw <- tuhDigits
-            let coff = if rkorbw <= 90
-                    then BrakingFriction rkorbw
-                    else BrakingEffect rkorbw
-            return $ RunwayCondition runway cover spread spreadheight coff
-
-fourDigits :: Parser Int
-fourDigits = (\a b c d -> read [a,b,c,d]) <$> digit <*> digit <*> digit <*> digit
-
-trieDigits :: Parser Int
-trieDigits = (\a b c -> read [a,b,c]) <$> digit <*> digit <*> digit
-
-tuhDigits :: Parser Int
-tuhDigits = (\a b -> read [a,b]) <$> digit <*> digit
-
-runwayDesignationParser :: Parser Runway
-runwayDesignationParser = choice ["R88" `means` AllRunways, oneRunway]
-    where
-        oneRunway = do
-            _ <- char 'R'
-            magheading <- (\a b -> read [a,b]) <$> digit <*> digit :: Parser Int
-            dir <- Nothing `option` (Just <$> choice
-                [ "L" `means` RWYLeft
-                , "R" `means` RWYRight
-                , "C" `means` RWYCenter ])
-            return $ Runway magheading dir
-
-trendParser :: Parser Trend
-trendParser = choice
-    [ "NOSIG" `means` NOSIG
-    , changeParser ]
-    where
-        changeParser :: Parser Trend
-        changeParser = do
-            changes <- changesParser :: Parser [Trend]
-            when (length changes /= 1) $ fail "A METAR contains exactly one transition"
-            return $ head changes
-
-changesParser :: Parser [Trend]
-changesParser = many1 $ skipSpace >> transitionTypeParser
-    where
-        transitionTypeParser :: Parser Trend
-        transitionTypeParser = choice
-                [ "TEMPO" `callsfor` (TEMPO <$> transitionParser)
-                , "BECMG" `callsfor` (BECMG <$> transitionParser)
-                , "PROB" `callsfor`  (PROB  <$> twoDigits <*> (head <$> changesParser)) ]
-        transitionParser :: Parser [Transition]
-        transitionParser = sepBy1' oneTransition (char ' ')
-        oneTransition = do
-            skipSpace
-            choice . map try $
-              [ TransClouds    <$> cloudParser
-              , TransWind      <$> windParser
-              , TransVis       <$> many1' visibilityParser
-              , TransWX        <$> count 1 wxParser
-              , TransRunwayVis <$> sepBy' runwayvisParser (char ' ') ]
-
-twoDigits :: Parser Int
-twoDigits = (\a b -> read [a,b]) <$> digit <*> digit
-
-metarParser :: Parser Weather
-metarParser = do
-    _ <- string "METAR"
-    reportflags <- flagsParser
-    identifier <- skipSpace >> stationParser
-    reportdate <- skipSpace >> dateParser
-    reportflags2 <- flagsParser
-    reportwind <- Nothing `option` (skipSpace >> Just <$> windParser)
-    skipSpace
-    reportvis <- [TenOrMore] `option` many1 visibilityParser
-    skipSpace
-    reportrunwaycond <- sepBy' runwayconditionParser (char ' ')
-    reportrunwayvis <- sepBy' runwayvisParser (char ' ')
-    reportwx <- many' wxParser
-    reportclouds <- [] `option` (skipSpace >> cloudParser)
-    (reporttemp, reportdewpoint) <- (Nothing, Nothing) `option` (skipSpace >> tdParser >>= \(w,d) -> return (Just w, Just d))
-    reportpressure <- Nothing `option` (skipSpace >> Just <$> pressureParser)
-    void $ many' $ skipSpace >> pressureParser -- Sometimes, multiple pressure values are offered
-    skipSpace
-    reporttrend <- NOTAVAIL `option` trendParser
-    reportrmk <- maybeRMK
-    skipSpace
-    _ <- choice $ map char "=$"
-    return $ METAR reportdate identifier (reportflags ++ reportflags2)
-        reportwind reportvis reportrunwayvis reportrunwaycond reportwx
-        reportclouds reportpressure reporttemp reportdewpoint
-        reporttrend reportrmk
-
-maybeRMK :: Parser (Maybe Text)
-maybeRMK = Nothing `option` do
-    void $ choice [ string "RMK ", string " RMK " ]
-    Just . pack <$> many1 (satisfy (notInClass "$="))
-
--- | An attoparsec parser that can parse METAR messages.
-weatherParser :: Parser Weather
-weatherParser = metarParser
-
-maybeOneSpace :: Parser ()
-maybeOneSpace = perhaps_ space
-
--- | Parse the given METAR text.
-parseWeather :: Text -> Either String Weather
-parseWeather = parseOnly weatherParser
+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}++-- |+-- Module: Data.Aviation.WX+-- Copyright: (C) 2014-2016, Hans-Christian Esperer+-- License: MIT+-- Maintainer: Hans-Christian Esperer <hc@hcesperer.org>+-- Stability: experimental+-- Portability: portable+--+-- Parse aviation weather reports. A qualified import is recommended.+module Data.Aviation.WX(+  weatherParser+  , Weather(..)+  , HasWeather(..)+  , AsWeather(..)+  , Date(..)+  , HasDate(..)+  , Station(..)+  , Flag(..)+  , HasFlag(..)+  , AsFlag(..)+  , Wind(..)+  , HasWind(..)+  , Visibility(..)+  , HasVisibility(..)+  , AsVisibility(..)+  , Runway(..)+  , HasRunway(..)+  , AsRunway(..)+  , VisTrend(..)+  , HasVisTrend(..)+  , AsVisTrend(..)+  , RunwayCondition(..)+  , HasRunwayCondition(..)+  , AsRunwayCondition(..)+  , WeatherPhenomenon(..)+  , HasWeatherPhenomenon(..)+  , Cloud(..)+  , HasCloud(..)+  , AsCloud(..)+  , Pressure(..)+  , HasPressure(..)+  , AsPressure(..)+  , Trend(..)+  , HasTrend(..)+  , AsTrend(..)+  , WPDesc(..)+  , HasWPDesc(..)+  , AsWPDesc(..)+  , WPPrecipitation(..)+  , HasWPPrecipitation(..)+  , AsWPPrecipitation(..)+  , WPObfuscation(..)+  , HasWPObfuscation(..)+  , AsWPObfuscation(..)+  , WPOther(..)+  , HasWPOther(..)+  , AsWPOther(..)+  , Distance(..)+  , HasDistance(..)+  , AsDistance(..)+  , Direction(..)+  , HasDirection(..)+  , AsDirection(..)+  , RwyCoverType(..)+  , HasRwyCoverType(..)+  , AsRwyCoverType(..)+  , RunwayBraking(..)+  , HasRunwayBraking(..)+  , AsRunwayBraking(..)+  , Vertical(..)+  , HasVertical(..)+  , AsVertical(..)+  , WindDirection(..)+  , HasWindDirection(..)+  , AsWindDirection(..)+  , Cover(..)+  , HasCover(..)+  , AsCover(..)+  , CloudType(..)+  , HasCloudType(..)+  , AsCloudType(..)+  , WPIntensity(..)+  , HasWPIntensity(..)+  , AsWPIntensity(..)+  , Transition(..)+  , HasTransition(..)+  , AsTransition(..)+  , Unit(..)+  , HasUnit(..)+  , AsUnit(..)+  ) where++import Control.Applicative(Alternative((<|>), some, many), optional)+import Control.Lens(makeClassy, makeClassyPrisms, makeWrapped)+import Control.Monad(when, void)+import Data.Maybe(isNothing, catMaybes)+import Data.Text(Text, pack)+import Text.Parser.Char(CharParsing, space, spaces, char, satisfy, text, digit, anyChar)+import Text.Parser.Combinators(try, option, choice, sepBy, sepBy1, count)++takeChars ::+  CharParsing f =>+  Int+  -> f Text+takeChars n =+  pack <$> count n anyChar++-- | Aviation weather, currently only METARs are supported.+data Weather+    = -- | A METeorological Aerodrome Report+      METAR+    { -- | The observation date.+      _metardate        :: Date+    , -- | The designation of the observing station.+      _station     :: Station+    , -- | A remark about the reported observation.+      _flags       :: [Flag]+    , -- | The observed wind.+      _metarwind        :: Maybe Wind+    , -- | The observed visibility.+      _metarvisibility  :: [Visibility]+    , -- | The observed visibility for specific runways,+      -- usually reported if the runway visibility significantly+      -- differs from the general reported visibility.+      _runwayvis   :: [(Runway, [Visibility], Maybe VisTrend)]+    , -- | Surface or close conditions of a specific runway.+      _runwaycond  :: [RunwayCondition]+    , -- | Observed weather phenomena+      _wx          :: [WeatherPhenomenon]+    , -- | Observed cloud layers+      _clouds      :: [Cloud]+    , -- | Measured pressure+      _metarpressure    :: Maybe Pressure+    , -- | Measured pressure+      _temperature :: Maybe Int+    , -- | Determined dew point+      _dewPoint    :: Maybe Int+    , -- | Expected changes within the next two hours+      _weathertrend       :: Trend+    , -- | RMK section (Additional parts of a METAR report that are not+      -- part of the official METAR message but are commonly used+      -- in various parts of the world; unparsed)+      _remark      :: Maybe Text+    , --+      _maintenance :: Bool }+    | -- | An automatic terminal information service report+      ATIS+    | -- | A non-scheduled METAR+      SPECI+    | -- | A terminal aerodrome forecast+      TAF+    | -- | An aviation wx hazard message of moderate severity+      AIRMET+    | -- | A significant meteorological information message+      SIGMET+    | -- | A general aviation forecast message+      GAMET+    deriving (Eq, Show)++-- | A flag describing an aviation meteorological report+data Flag+    = -- | A message has been corrected after the beginning of+      -- its original validity period+      COR+    | -- | A message has been corrected prior to its+      -- original validity period+      AMD+    | -- | A message has been generated fully automatic+      -- without a plausibility check by a human+      AUTO+    deriving (Eq, Show)++-- | The trend part of a METAR message specifies expected+-- changes in weather conditions within the next two hours.+-- A Trend/Transition part of a TAF message specified expected+-- changes in weather conditions within the specified range.+data Trend+    = -- | A transition that will start within the defined+      -- time frame and be completed at the end of the defined+      -- time frame+      BECMG [Transition]+    | -- | A transition that will start within the defined+      -- time frame and be finished at the end of the defined+      -- time frame+      TEMPO [Transition]+    | -- | A probability specification.+      -- As one of my FIs (ex-atc at EDDF) used to put it:+      -- 30% means "I'm quite sure it won't happen but will still+      -- put it in here, in case it does after all."+      -- 40% means "I'm certain it will happen but will still+      -- put it with 40%, in case it does not happen after all."+      PROB Int Trend+    | -- | NOSIG is only applicable to METARs. It means that+      -- no significant changes are expected within the next+      -- two hours.+      NOSIG+    | -- | NOTAVAIL is only applicable to METARs. It means that+      -- the METAR message in question does not contain a TREND+      -- section.+      NOTAVAIL+    deriving (Eq, Show)++-- | A transition in weather conditions.+-- A transition can either be temporary or permanent;+-- this will be encoded in the container structure.+data Transition+    = -- | A change of wind strength or direction+      TransWind Wind+    | -- | A change of visibility+      TransVis [Visibility]+    | -- | A change of visibility for a specific runway+      TransRunwayVis [(Runway, [Visibility], Maybe VisTrend)]+    | -- | A change of weather phenomenon+      TransWX [WeatherPhenomenon]+    | -- | A change of ceiling or cloud layers+      TransClouds [Cloud]+    deriving (Eq, Show)++-- | A visibility trend specifically for runway conditions+data VisTrend+    = -- | Visibility will improve (maybe do wait a bit)+      VisTrendUpward+    | -- | Visibility will deteriorate (still, don't rush+      -- the take off and use proper phraseology at all times)+      VisTrendDownward+    | -- | No expected change in runway visibility conditions+      VisTrendNoDistinctTendency+    deriving (Eq, Show)++-- | A pressure value. This is intentionally coded+-- individually and not converted to a specific reference.+data Pressure+    = -- | The QNH value in hectopascals. QNH is the current+      -- pressure at sea level, corrected for pressure and+      -- temperature changes at the station level.+      QNH Int+    | -- | The same as QNH, only in inches+      -- (Do you know the old joke?:+      --   * ATC: Liner 1723 descend to 3,000ft, the QNH is 1013mb.+      --   * Liner 1723: Uh, approach, can we have that in inches please?+      --   * ATC: Liner 1723 descend to 36,000 inches, the QNH is 1013mb.+      Altimeter Int+    | -- | The current pressure at station level in hectopascals.+      QFE Int+    | -- | The current pressure at sea level in hectopascals.+      QFF Int+    deriving (Eq, Show)++-- | A weather phenomenon.+-- This can be an observed phenomenon in the case of METARs or an+-- expected phenomenon in the case of TAFs.+data WeatherPhenomenon+    = Phenomenon+    { -- | The intensity of the phenomenon.+      _intensity :: WPIntensity+    , -- | The description of the weather phenomenon.+      _desc      :: Maybe WPDesc+    , -- | The precipitation type of the weather phenomenon.+      _prec      :: Maybe WPPrecipitation+    , -- | The effects of the phenomenon on the visibility+      _obfus     :: Maybe WPObfuscation+    , -- | Other details about the phenomenon.+      _other     :: Maybe WPOther }+    deriving (Eq, Show)++-- | The intensity of an observed or expected weather phenomenon.+data WPIntensity+    = -- | Light+      Light+    | -- | Moderate+      Moderate+    | -- | Heavy+      Heavy+    | -- | Only applicable to METARs. The weather phenomenon was+      -- observed in the vicinity of the observed area, not within+      -- the observed area itself.+      Vicinity+    | -- | Only applicable to METARs. The weather phenomenon was+      -- recently observed in the past, but was not observed at+      -- the time the report was issued.+      Recent+    deriving (Enum, Eq, Show)++-- | The description of a weather phenomenon.+data WPDesc+    = -- | Shallow.+      Shallow+    | -- | Patches.+      Patches+    | -- | Partial.+      WXPartial+    | -- | Low, drifting.+      LowDrifting+    | -- | Blowing.+      Blowing+    | -- | Shower.+      Shower+    | -- | Thunderstorm.+      Thunderstorm+    | -- | Freezing.+      Freezing+    deriving (Enum, Eq, Ord, Show)++-- | The type of the precipitation+data WPPrecipitation+    = -- | Drizzle.+      Drizzle+    | -- | Rain.+      Rain+    | -- | Snow.+      Snow+    | -- | Snow grains.+      ShowGrains+    | -- | Ice crystals.+      IceCrystals+    | -- | Ice pellets.+      IcePellets+    | -- | Hail.+      Hail+    | -- | Snow pellets.+      SnowPellets+    | -- | Unknown type of precipitation.+      UnknownPrecipitation+    deriving (Enum, Eq, Ord, Show)++-- | Effects on the visibility by a weather phenomenon+data WPObfuscation+    = -- | Mist. Visibility impaired but still greater than 1000m+      Mist+    | -- | Fog. Visibility less than 1000m.+      Fog+    | -- | Smoke.+      Smoke+    | -- | Volcanic ash.+      VolcanicAsh+    | -- | Dust.+      Dust+    | -- | Sand.+      Sand+    | -- | Haze.+      Haze+    deriving (Enum, Eq, Ord, Show)++-- | Other important information about a weather phenomenon.+data WPOther+    = -- | Dust or sand whirls.+      DustOrSandwhirls+    | -- | Squalls.+      Squalls+    | -- | Tornado.+      Tornado+    | -- | Sand storm.+      Sandstorm+    | -- | Dust storm.+      Duststorm+    deriving (Enum, Eq, Ord, Show)++-- | The Distance.+data Distance+    = -- | The distance in metres.+      Metres Int+    | -- | The distance in km.+      KM Int+    | -- | The distance in statute miles.+      SM Int+    | -- | The distance in nautical miles.+      NM Int+    deriving (Eq, Show)++-- | Vertical visibility.+data Visibility+    = -- | Ten kilometres or more.+      TenOrMore+    | -- | Fifty metres or less.+      FiftyMetresOrLess+    | -- | Two kilometres or more.+      TwoOrMore+    | -- | A specific visibility.+      SpecificVisibility Distance (Maybe Direction)+    deriving (Eq, Show)++-- | Directions.+data Direction+    = -- | North.+      North+    | -- | South.+      South+    | -- | East.+      East+    | -- | West.+      West+    | -- | Northwest.+      NorthWest+    | -- | Northeast.+      NorthEast+    | -- | Southwest.+      SouthWest+    | -- | Southeast.+      SouthEast+    | -- | Left runway for runways of the same QFU+      -- (part of the runway designator)+      RWYLeft+    | -- | Right runway for runways of the same QFU+      -- (part of the runway designator)+      RWYRight+    | -- | Centre runway for runways of the same QFU+      -- (part of the runway designator)+      RWYCenter+    deriving (Eq, Show)++-- | Runway specification.+data Runway+    = -- | All runways.+      AllRunways+    | -- | A specific runway.+      SpecificRunway+    { -- | The runway's magnetic orientation, divided by ten and rounded.+      _runwayQFU                 :: Int+    , -- | For multiple runways with the same QFU, a left, right or centre+      -- selector is added.+      _runwayDirection           :: Maybe Direction }+    deriving (Eq, Show)++-- | The runway contamination type.+data RwyCoverType+    = -- | The runway is not contaminated.+      RCTDry+    | -- | The runway is moist.+      RCTMoist+    | -- | The runway is wet.+      RCTWet+    | -- | The runway is convered with rime.+      RCTRime+    | -- | The runway is covered with dry snow.+      RCTDrySnow+    | -- | The runway is covered with wet snow.+      RCTWetSnow+    | -- | The runway is covered with slush.+      RCTSlush+    | -- | The runway is covered with ice.+      RCTIce+    | -- | The runway is covered with frozen ruts or ridges.+      RCTFZRut+    | -- | The runway contamination type is unknown.+      RCTUnknown+    deriving (Eq, Show, Enum)++-- | Runway conditions.+data RunwayCondition+    = -- | Specific runway conditions exist.+      SpecificRunwayCondition+    { -- | The runway for which specific conditions+      -- have been observed.+      _rwcondRunway :: Runway+    , -- | Whether and how the runway is contamindated.+      _rwcondCover  :: RwyCoverType+    , -- | The extent of the contamination in percent.+      _rwcondSpread :: Maybe Int+    , -- | The height of the contamination in millimetres.+      _rwcondCoverHeight :: Maybe Int+    , -- | The friction coefficient or braking action value.+      _rwcondBrkCoeff :: RunwayBraking }+    | -- | The runway is closed.+      RwyClosed+    { -- | The runway that is closed.+      _rwclosedRunway :: Runway }+    | -- | The whole aerodrome is closed.+      ADClosed+    deriving (Eq, Show)++-- | The measured brake efficiency of a specific runway.+data RunwayBraking+    = -- | The friction coefficient.+      BrakingFriction Int+    | -- | The braking coefficient.+      BrakingEffect Int+    deriving (Eq, Show)++-- | An obersvation date.+data Date+    = Date {+      _dayOfMonth :: Int+    , _hour :: Int+    , _minute :: Int+    } deriving (Eq, Show)++-- | An aeronautical weather station designator.+newtype Station+    = -- | The station as identified by its aerodrome's+      -- ICAO code.+      ICAO Text+    deriving (Eq, Show)++-- | A vertical position specification.+data Vertical+    = -- | A vertical position with reference to the ground+      -- in feet.+      Height Int+    | -- | A vertical position with reference to the mean+      -- sea level/QNH in feet.+      Altitude Int+    | -- | A pressure altitude with reference to the+      -- standard QNH of 1013 hectopascals in hundrets of feet.+      FlightLevel Int+    | -- | Vertical position is not specified.+      VertNotSpec+    deriving (Eq, Show)++-- | Wind information.+data Wind+    = Wind+    { -- | The direction the wind is blowing from.+      _winddirection :: WindDirection+    , -- | The wind speed.+      _velocity  :: Unit+    , -- | The strength of the observed gusts, if any.+      _gusts     :: Maybe Int+    } deriving (Eq, Show)++-- | The direction the wind is blowing from.+data WindDirection+    = -- | The wind is blowing in equal or almost equal+      -- strength from a wide variety of directions.+      Variable+    | -- | The wind is blowing from the specified direction.+      -- Directions can be given with reference to true or+      -- magnetic north, depending on the type of weather+      -- observation/forecast message.+      Degrees Int+    | -- | The wind is blowing from a specific direction+      -- range.+      Varying+    { -- | The mean direction the wind is blowing from.+      _windmean :: Int+    , -- | The minimum direction the wind is blowing from.+      _windfrom :: Int+    , -- | The maximum direction the wind is blowing from.+      _windto   :: Int+    } deriving (Eq, Show)+     ++-- | A speed unit.+data Unit+    = -- | Nautical miles per hour+      Knots Int+    | -- | Statute miles per hour+      Miles Int+    | -- | Kilometres per hour+      KMH Int+    deriving (Eq, Show)++-- | A cloud specification.+data Cloud+    = -- | No specific clouds could be observed, because+      -- the (given) ground visibility was too low or because+      -- the ground is covered in clouds.+      VVis (Maybe Int)+    | -- | Clouds were observed.+      ObservedCloud Cover Vertical CloudType+    deriving (Eq, Show)++-- | The type of cloud.+data CloudType+    = -- | A cumulonimbus cloud.+      Cumulonimbus+    | -- | A developing cb cloud.+      ToweringCumulus+    | -- | A stratus cloud.+      Stratus+    | -- | A cumulus cloud.+      Cumulus+    | -- | A stratocumulus cloud.+      Stratocumulus+    | -- | An altostratus cloud.+      Altostratus+    | -- | An altocumulus cloud.+      Altocumulus+    | -- | A cirrostratus cloud.+      Cirrostratus+    | -- | A cirrus cloud.+      Cirrus+    | -- | An unclassified cloud.+      Unclassified+    deriving (Enum, Eq, Show)++-- | The area that is covered.+data Cover+    = -- | 1-2 eights are covered.+      FEW+    | -- | 3-4 eights are covered.+      SCT+    | -- | 5-7 eights are covered.+      BKN+    | -- | More than 7 eights are covered.+      OVC+    | -- | Cover not specified+      CoverNotSpecified+    deriving (Enum, Eq, Ord, Show)++makeClassy       ''Weather+makeClassyPrisms ''Weather+makeClassy       ''Flag+makeClassyPrisms ''Flag+makeClassy       ''Trend+makeClassyPrisms ''Trend+makeClassy       ''Transition+makeClassyPrisms ''Transition+makeClassy       ''VisTrend+makeClassyPrisms ''VisTrend+makeClassy       ''Pressure+makeClassyPrisms ''Pressure+makeClassy       ''WeatherPhenomenon+makeClassy       ''WPIntensity+makeClassyPrisms ''WPIntensity+makeClassy       ''WPDesc+makeClassyPrisms ''WPDesc+makeClassy       ''WPPrecipitation+makeClassyPrisms ''WPPrecipitation+makeClassy       ''WPObfuscation+makeClassyPrisms ''WPObfuscation+makeClassy       ''WPOther+makeClassyPrisms ''WPOther+makeClassy       ''Distance+makeClassyPrisms ''Distance+makeClassy       ''Visibility+makeClassyPrisms ''Visibility+makeClassy       ''Direction+makeClassyPrisms ''Direction+makeClassy       ''Runway+makeClassyPrisms ''Runway+makeClassy       ''RwyCoverType+makeClassyPrisms ''RwyCoverType+makeClassy       ''RunwayCondition+makeClassyPrisms ''RunwayCondition+makeClassy       ''RunwayBraking+makeClassyPrisms ''RunwayBraking+makeClassy       ''Date+makeWrapped      ''Station+makeClassy       ''Vertical+makeClassyPrisms ''Vertical+makeClassy       ''Wind+makeClassy       ''WindDirection+makeClassyPrisms ''WindDirection+makeClassy       ''Unit+makeClassyPrisms ''Unit+makeClassy       ''Cloud+makeClassyPrisms ''Cloud+makeClassy       ''CloudType+makeClassyPrisms ''CloudType+makeClassy       ''Cover+makeClassyPrisms ''Cover++instance HasWPIntensity WeatherPhenomenon where+  wPIntensity =+    intensity . wPIntensity++instance HasWindDirection Wind where+  windDirection =+    winddirection . windDirection++instance HasUnit Wind where+  unit = +    velocity . unit+    +stationParser :: CharParsing f => f Station+stationParser = ICAO <$> takeChars 4++dateParser :: CharParsing f => f Date+dateParser = Date <$> twin <*> twin <*> (twin <* text "Z")+    where twin = (\a b -> read [a, b]) <$> digit <*> digit++variableWindParser :: (Monad f, CharParsing f) => WindDirection -> f WindDirection+variableWindParser (Degrees meanWind) = try $ do+    dir1 <- (\a b c -> read [a, b, c]) <$> digit <*> digit <*> digit+    _ <- char 'V'+    dir2 <- (\a b c -> read [a, b, c]) <$> digit <*> digit <*> digit+    return $ Varying meanWind dir1 dir2+variableWindParser _ = fail "Erroneous parameters"++windParser :: (Monad f, CharParsing f) => f Wind+windParser = do+    dir <- choice [readwinddir, variablewind]+    str <- readwindstr+    gustsies <- option Nothing readgusts+    unit' <- readunit+    dir2 <- option dir $ char ' ' >> variableWindParser dir+    return $ Wind dir2 (unit' str) gustsies+    where+        variablewind = "VRB" `means` Variable+        readwinddir = (\a b c -> Degrees . read $ [a, b, c]) <$> digit <*> digit <*> digit+        readwindstr = (\a b -> read [a, b]) <$> digit <*> digit+        readunit = choice [ "KT" `means` Knots+                          , "MPH" `means` Miles+                          , "KM" `means` KMH]+        readgusts = (\_ b c -> Just . read $ [b, c]) <$> char 'G' <*> digit <*> digit++pressureParser :: CharParsing f => f  Pressure+pressureParser = choice [qnh, mmhg]+    where+      qnh = (\_ a b c d -> QNH $ read [a, b, c, d]) <$> char 'Q' <*> digit <*> digit <*> digit <*> digit+      mmhg = (\_ a b c d -> Altimeter $ read [a, b, c, d]) <$> char 'A' <*> digit <*> digit <*> digit <*> digit++wxParser :: (Monad f, CharParsing f) => f WeatherPhenomenon+wxParser = do+    spaces+    intsy <- intensityParser+    dsc <- perhaps descParser+    prc <- perhaps precipitationParser+    obfs <- perhaps obfuscationParser+    othr <- perhaps otherParser+    when ( (== 0) . Prelude.length . Prelude.filter not $+        [ isNothing dsc, isNothing prc+        , isNothing obfs, isNothing othr ] ) $ fail ""+    return $ Phenomenon intsy dsc prc obfs othr++perhaps :: Alternative m => m a -> m (Maybe a)+perhaps parser = option Nothing $ Just <$> parser++perhaps_ :: Alternative f => f a -> f ()+perhaps_ parser = void $ perhaps parser++callsfor :: (CharParsing m, Monad m) => Text -> m b -> m b+a `callsfor` b = text a >> b++means :: (CharParsing m, Monad m) => Text -> b -> m b+a `means` b = text a >> return b++means' :: (CharParsing m, Monad m) => Text -> a -> m a+a `means'` b = try $ spaces >> text a >> spaces >> return b++descParser :: (Monad f, CharParsing f) => f WPDesc+descParser = choice+    [ "MI" `means` Shallow+    , "BC" `means` Patches+    , "PR" `means` WXPartial+    , "DR" `means` LowDrifting+    , "BL" `means` Blowing+    , "SH" `means` Shower+    , "TS" `means` Thunderstorm+    , "FZ" `means` Freezing ]++precipitationParser :: (Monad f, CharParsing f) => f WPPrecipitation+precipitationParser = choice+    [ "DZ" `means` Drizzle+    , "RA" `means` Rain+    , "SN" `means` Snow+    , "SG" `means` ShowGrains+    , "IC" `means` IceCrystals+    , "PL" `means` IcePellets+    , "GR" `means` Hail+    , "GS" `means` SnowPellets+    , "UP" `means` UnknownPrecipitation ]++obfuscationParser :: (Monad f, CharParsing f) => f WPObfuscation+obfuscationParser = choice+    [ "BR" `means` Mist+    , "FG" `means` Fog+    , "FU" `means` Smoke+    , "VA" `means` VolcanicAsh+    , "DU" `means` Dust+    , "SA" `means` Sand+    , "HZ" `means` Haze ]++otherParser :: (Monad f, CharParsing f) => f WPOther+otherParser = choice+    [ "PO" `means` DustOrSandwhirls+    , "SQ" `means` Squalls+    , "FC" `means` Tornado+    , "SS" `means` Sandstorm+    , "DS" `means` Duststorm ]++intensityParser :: (Monad f, CharParsing f) => f WPIntensity+intensityParser = option Moderate $ choice+    [ char '-' >> return Light+    , char '+' >> return Heavy+    , "VC" `means` Vicinity+    , "RE" `means` Recent ]++visibilityParser :: (Monad f, CharParsing f) => f Visibility+visibilityParser = spaces >> choice [ tenormore, arb, arb1, metres ]+    where+        tenormore = text "9999" >> return TenOrMore+        metres = (\a b c d dir -> SpecificVisibility (visunit $ read [a,b,c,d]) dir) <$> digit <*> digit <*> digit <*> digit <*> directionParser+        visunit :: Int -> Distance+        visunit n = if n > 5000+            then KM (n `quot` 1000)+            else Metres n+        arb  = (\a b unit' -> SpecificVisibility (unit' $ read [a,b])) <$> digit <*> digit <*> distanceUnitParser <*> directionParser+        arb1 = (\a unit' -> SpecificVisibility (unit' $ read ['0', a])) <$> digit <*> distanceUnitParser <*> directionParser++directionParser :: (Monad f, CharParsing f) => f (Maybe Direction)+directionParser = Nothing `option` (Just <$> choice+    [ "NE" `means` NorthEast, "NW" `means` NorthWest+    , "SE" `means` SouthEast, "SW" `means` SouthWest+    , "N" `means` North, "S" `means` South+    , "E" `means` East, "W" `means` West ])++distanceUnitParser :: (Monad f, CharParsing f) => f (Int -> Distance)+distanceUnitParser = choice+    [ "KM" `means` KM+    , "SM" `means` SM+    , "NM" `means` NM ]++cloudParser :: (Monad f, CharParsing f) => f [Cloud]+cloudParser = choice [(:[]) <$> vvisParser, nsc, cavok, clr, sepBy1 clds (char ' ')]+    where+        clds = do+            perhaps_ space+            intsy <- cloudIntensityParser+            height <- choice+                [ "///" `means` VertNotSpec+                , (\a b c -> Height $ (* 100) $ read [a, b, c]) <$> digit <*> digit <*> digit ]++            cloudType' <- cloudTypeParser+            return $ ObservedCloud intsy height cloudType'+        cavok = spaces >> "CAVOK" `means` []+        nsc = spaces >> "NSC" `means` []+        clr = spaces >> "CLR" `means` []++vvisParser :: (Monad f, CharParsing f) => f Cloud+vvisParser = do+    _ <- text "VV"+    choice+        [ "///" `means` VVis Nothing+        , (\a b c -> VVis . Just . read $ [a,b,c]) <$> digit <*> digit <*> digit ]++cloudIntensityParser :: (Monad f, CharParsing f) => f Cover+cloudIntensityParser = choice+    [ "FEW" `means` FEW+    , "SCT" `means` SCT+    , "BKN" `means` BKN+    , "OVC" `means` OVC+    , "///" `means` CoverNotSpecified ]++cloudTypeParser :: (Monad f, CharParsing f) => f CloudType+cloudTypeParser = option Unclassified $ choice+    [ "CB" `means` Cumulonimbus+    , "TCU" `means` ToweringCumulus+    , "ST" `means` Stratus+    , "CU" `means` Cumulus+    , "SC" `means` Stratocumulus+    , "AS" `means` Altostratus+    , "AC" `means` Altocumulus+    , "CS" `means` Cirrostratus+    , "CI" `means` Cirrus+    , "///" `means` Unclassified]++perhapsMinus :: (Monad f, CharParsing f) => f String+perhapsMinus = "" `option` (char 'M' >> return "-")++tdParser :: (Monad f, CharParsing f) => f (Int, Int)+tdParser = do+    tmpr <- (\pm a b -> read (pm ++ [a, b]) :: Int) <$> perhapsMinus <*> digit <*> digit+    _ <- char '/'+    dewpoint <- (\pm a b -> read (pm ++ [a, b]) :: Int) <$> perhapsMinus <*> digit <*> digit+    return (tmpr, dewpoint)++flagsParser :: (Monad f, CharParsing f) => f [Flag]+flagsParser = many $ choice+    [ "COR" `means'` COR+    , "AMD" `means'` AMD+    , "AUTO" `means'` AUTO ]++runwayvisParser ::  (Monad f, CharParsing f) => f (Runway, [Visibility], Maybe VisTrend)+runwayvisParser = do+    runway' <- runwayDesignationParser+    _ <- char '/'+    vis <- parseRwyVis+    vistrend <- Nothing `option` (Just <$> choice+        [ "D" `means` VisTrendDownward+        , "N" `means` VisTrendNoDistinctTendency+        , "U" `means` VisTrendUpward ] )+    return (runway', vis, vistrend)+    where+        parseRwyVis = do+            worstvis <- Nothing `option` (Just <$> choice visspec <* text "V")+            vis <- Just <$> choice visspec+            return $ catMaybes [worstvis, vis]+                        +        visspec =+            [ "M0050" `means` FiftyMetresOrLess+            , "P2000" `means` TwoOrMore+            , fourDigits >>= \a -> return $ SpecificVisibility (Metres a) Nothing+            , trieDigits >>= \a -> return $ SpecificVisibility (Metres a) Nothing ]+                        +runwayconditionParser ::  (Monad f, CharParsing f) => f RunwayCondition+runwayconditionParser = do+    runway' <- runwayDesignationParser+    _ <- char '/'+    choice+        [ "SNOCLO" `means` ADClosed+        , rwycond runway' ]++    where+        rwycond runway' = do+            cover' <- RCTUnknown `option` ((toEnum . read . (:[])) <$> digit)+            spread <- choice+                [ char '/' >> return Nothing+                , (Just . read . (:[])) <$> digit ]+            spreadheight <- choice+                [ text "//" >> return Nothing+                , Just <$> tuhDigits ]+            rkorbw <- tuhDigits+            let coff = if rkorbw <= 90+                    then BrakingFriction rkorbw+                    else BrakingEffect rkorbw+            return $ SpecificRunwayCondition runway' cover' spread spreadheight coff++fourDigits :: CharParsing f => f Int+fourDigits = (\a b c d -> read [a,b,c,d]) <$> digit <*> digit <*> digit <*> digit++trieDigits :: CharParsing f => f Int+trieDigits = (\a b c -> read [a,b,c]) <$> digit <*> digit <*> digit++tuhDigits :: CharParsing f => f Int+tuhDigits = (\a b -> read [a,b]) <$> digit <*> digit++runwayDesignationParser :: (Monad f, CharParsing f) => f Runway+runwayDesignationParser = choice ["R88" `means` AllRunways, oneRunway]+    where+        oneRunway = do+            _ <- char 'R'+            magheading <- (\a b -> read [a,b]) <$> digit <*> digit+            dir <- Nothing `option` (Just <$> choice+                [ "L" `means` RWYLeft+                , "R" `means` RWYRight+                , "C" `means` RWYCenter ])+            return $ SpecificRunway magheading dir++trendParser :: (Monad f, CharParsing f) => f Trend+trendParser = choice+    [ "NOSIG" `means` NOSIG+    , changeParser ]+    where+        changeParser = do+            changes <- changesParser+            when (length changes /= 1) $ fail "A METAR contains exactly one transition"+            return $ head changes++changesParser :: (Monad f, CharParsing f) => f [Trend]+changesParser = some $ spaces >> transitionTypeParser+    where+        transitionTypeParser = choice+                [ "TEMPO" `callsfor` (TEMPO <$> transitionParser)+                , "BECMG" `callsfor` (BECMG <$> transitionParser)+                , "PROB" `callsfor`  (PROB  <$> twoDigits <*> (head <$> changesParser)) ]+        transitionParser = sepBy1 oneTransition (char ' ')+        oneTransition = do+            spaces+            choice . map try $+              [ TransClouds    <$> cloudParser+              , TransWind      <$> windParser+              , TransVis       <$> some visibilityParser+              , TransWX        <$> count 1 wxParser+              , TransRunwayVis <$> sepBy runwayvisParser (char ' ') ]++twoDigits :: CharParsing f => f Int+twoDigits = (\a b -> read [a,b]) <$> digit <*> digit++metarParser :: (Monad f, CharParsing f) => f Weather+metarParser = do+    _ <- text "METAR"+    reportflags <- flagsParser+    identifier <- spaces >> stationParser+    reportdate <- spaces >> dateParser+    reportflags2 <- flagsParser+    reportwind <- Nothing `option` (spaces >> Just <$> windParser)+    spaces+    reportvis <- [TenOrMore] `option` some visibilityParser+    spaces+    reportrunwaycond <- sepBy runwayconditionParser (char ' ')+    reportrunwayvis <- sepBy runwayvisParser (char ' ')+    reportwx <- many wxParser+    reportclouds <- [] `option` (spaces >> cloudParser)+    (reporttemp, reportdewpoint) <- (Nothing, Nothing) `option` (spaces >> tdParser >>= \(w,d) -> return (Just w, Just d))+    reportpressure <- Nothing `option` (spaces >> Just <$> pressureParser)+    void $ many $ spaces >> pressureParser -- Sometimes, multiple pressure values are offered+    spaces+    reporttrend <- NOTAVAIL `option` trendParser+    reportrmk <- maybeRMK+    spaces+    maintenance' <- or <$> optional (True <$ char '$' <|> False <$ char '=')+    return $ METAR reportdate identifier (reportflags ++ reportflags2)+        reportwind reportvis reportrunwayvis reportrunwaycond reportwx+        reportclouds reportpressure reporttemp reportdewpoint+        reporttrend reportrmk maintenance'++maybeRMK :: (Monad f, CharParsing f) => f (Maybe Text)+maybeRMK = Nothing `option` do+    void $ choice [ text "RMK ", text " RMK " ]+    Just . pack <$> some (satisfy (`notElem` ("$=" :: String)))++-- | An attoparsec parser that can parse METAR messages.+weatherParser :: (Monad f, CharParsing f) => f Weather+weatherParser = metarParser
src/Data/Aviation/WX/Fetcher.hs view
@@ -1,21 +1,30 @@-module Data.Aviation.WX.Fetcher where+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-} -import Data.Char-import Data.List (filter)-import Data.Text (pack)-import Network.HTTP+module Data.Aviation.WX.Fetcher(+  parseWeather+, fetchMetar+) where -import Data.Aviation.WX+import Data.Attoparsec.Text(parseOnly)+import Data.Aviation.WX(Weather, weatherParser)+import Data.Char(toUpper, isAlpha)+import Data.Text(Text, pack)+import Network.HTTP(simpleHTTP, getRequest, getResponseBody)  type ICAOStationDesignator = String +-- | Parse the given METAR text.+parseWeather :: Text -> Either String Weather+parseWeather = parseOnly weatherParser+ fetchMetar :: ICAOStationDesignator -> IO (Either String Weather) fetchMetar icao = do     let icao' = map toUpper . filter isAlpha $ icao     metarString <- simpleHTTP (getRequest $ url icao') >>= getResponseBody-    let wx = pack $ "METAR " ++ relLine metarString ++ "="-    putStrLn $ "Parsing " ++ show wx-    return $ parseWeather wx+    let wx' = pack $ "METAR " ++ relLine metarString+    putStrLn $ "Parsing " ++ show wx'+    return $ parseWeather wx'     where-        url designator = "http://weather.noaa.gov/pub/data/observations/metar/stations/" ++ designator ++ ".TXT"+        url designator = "http://tgftp.nws.noaa.gov/data/observations/metar/stations/" ++ designator ++ ".TXT"         relLine s = Prelude.lines s !! 1
test/Spec.hs view
@@ -4,10 +4,15 @@     ) where  import Control.Monad+import Data.Attoparsec.Text (parseOnly) import Data.Text  import Data.Aviation.WX +-- | Parse the given METAR text.+parseWeather :: Text -> Either String Weather+parseWeather = parseOnly weatherParser+ frankfurt   :: Text frankfurt   = "METAR EDDF 010203Z 14032KT 130V240 9999 FEW017 SCT023CB BKN042 42/23 Q1029 NOSIG=" @@ -20,13 +25,13 @@ main :: IO () main = do     let Right frankfurt' = parseWeather frankfurt-    unless (temperature frankfurt' == Just 42) $ error "Temperature Frankfurt should be 42 degrees"-    unless (dewPoint frankfurt' == Just 23) $ error "Dew point Frankfurt should be 23 degrees"+    unless (_temperature frankfurt' == Just 42) $ error "Temperature Frankfurt should be 42 degrees"+    unless (_dewPoint frankfurt' == Just 23) $ error "Dew point Frankfurt should be 23 degrees"      let Right juliana' = parseWeather juliana-    unless (temperature juliana' == Just 29) $ error "It's 29 degrees in St. Maarten!"-    unless (dewPoint juliana' == Just 24) $ error "What's with the dew point in St. Maarten?"+    unless (_temperature juliana' == Just 29) $ error "It's 29 degrees in St. Maarten!"+    unless (_dewPoint juliana' == Just 24) $ error "What's with the dew point in St. Maarten?"      let Right loxt' = parseWeather loxt-    unless (temperature loxt' == Just 27) $ error "Temperature LOXT should be 27 degrees centigrade!"-    unless (dewPoint loxt' == Just 12) $ error "Dew point LOXT should be 12 degrees centigrade!"+    unless (_temperature loxt' == Just 27) $ error "Temperature LOXT should be 27 degrees centigrade!"+    unless (_dewPoint loxt' == Just 12) $ error "Dew point LOXT should be 12 degrees centigrade!"