package Exercises import scalaz._ import Scalaz._ object reader3 { trait OnOffDevice { def on: String def off: String } trait SensorDevice { def isCoffeePresent: Boolean } trait PowerConfig { def getPowerVolts(country: String): Int def isUSStandard(volt: Int): Boolean } trait OnOffComponent { def onOffDevice: OnOffDevice } trait SensorComponent { def sensorDevice: SensorDevice } trait Device extends OnOffComponent with SensorComponent trait DeviceComponent { def onOffDevice: OnOffDevice def sensorDevice: SensorDevice } trait PowerComponent { def powerConfig: PowerConfig } trait Appliance extends DeviceComponent with PowerComponent object Appliance { val appliance = Reader[Appliance,Appliance](identity) val onOffDevice = appliance map {_.onOffDevice} val sensorDevice = appliance map {_.sensorDevice} val powerConfig = appliance map {_.powerConfig} } object OnOffDevice { import Appliance.onOffDevice def on: Reader[Appliance,String] = onOffDevice map { _.on } def off: Reader[Appliance,String] = onOffDevice map { _.off } } object SensorDevice { import Appliance.sensorDevice def isCoffeePresent: Reader[Appliance,Boolean] = sensorDevice map { _.isCoffeePresent } } object PowerConfig { import Appliance.powerConfig def getPowerVolts(country: String) = powerConfig map {_.getPowerVolts(country)} def isUSStandard(volts: Int) = powerConfig map {_.isUSStandard(volts)} } object OnOffService { def on = for { ison <- OnOffDevice.on } yield ison def off = for { isoff <- OnOffDevice.off } yield isoff } object SensorService { def isCoffeePresent = for { hasCoffee <- SensorDevice.isCoffeePresent } yield hasCoffee } object PowerService { def isUSStandard(country: String) = for { is110v <- PowerConfig.getPowerVolts(country) isUSS <- PowerConfig.isUSStandard(is110v) } yield isUSS } class OnOffDeviceImpl extends OnOffDevice { def on = "SomeDevice.On" def off = "SomeDevice.Off" } class SensorDeviceImpl extends SensorDevice { def isCoffeePresent = true } class PowerConfigImpl extends PowerConfig { def getPowerVolts(country: String) = country match { case "USA" => 110
case "UK" => 220
case "HK" => 220
case "CHN" => 110
case _ => 0 } def isUSStandard(volts: Int) = volts === 110 } object MockOnOffDevice extends OnOffDeviceImpl object MockSensorDevice extends SensorDeviceImpl object MockPowerConfig extends PowerConfigImpl trait OnOffFunctions extends OnOffComponent { def onOffDevice = MockOnOffDevice } trait SensorFunctions extends SensorComponent { def sensorDevice = MockSensorDevice } trait DeviceFunctions extends DeviceComponent { def onOffDevice = MockOnOffDevice def sensorDevice = MockSensorDevice } trait PowerFunctions extends PowerComponent { def powerConfig = MockPowerConfig } object MockAppliance extends Appliance with DeviceFunctions with PowerFunctions def trigger =
if ((PowerService.isUSStandard("CHN")(MockAppliance)) && (SensorService.isCoffeePresent(MockAppliance))) OnOffService.on(MockAppliance) else OnOffService.off(MockAppliance) //&