Haskell中的成语状态循环

时间:2018-07-26 00:09:41

标签: haskell

在Haskell中是否有惯用的方式来表达以下代码?

//using it without latestWith - lets me autocomplete but requires
//typing first

import { CityService } from "../services/city-list.service";
import { Component, OnInit, OnDestroy } from "@angular/core";
import { City } from "../models/city";
import { Subscription, Observable } from "rxjs";
import {
  map,
  filter,
  startWith,
  withLatestFrom,
  debounceTime
} from "rxjs/operators";
import {
  FormGroup,
  FormControl,
  FormBuilder,
  Validators,
  NgForm,
  Form
} from "@angular/forms";

@Component({
  selector: "app-city-list",
  templateUrl: "./city-list.component.html",
  styleUrls: ["./city-list.component.css"]
})
export class CityListComponent implements OnInit {
  cities: City[];
citySub: Subscription;
  destinationCitySub: Observable<City[]>;
  originCitySub: Observable<City[]>;

  instantFlightForm: FormGroup;

  constructor(public cityService: CityService, private fb: FormBuilder) {

  }

  ngOnInit() {
    this.instantFlightForm = this.fb.group({
      destinationCity: [""],
      originCity: ["", Validators.required],
      startDate: []
    });



    this.cityService.getCities();
    this.citySub = this.cityService.getCityUpdateListener().subscribe(c=>this.cities=c);
   this.destinationCitySub = this.valueChange('destinationCity');

  }

  private valueChange(string) {
    return this.instantFlightForm.get(string).valueChanges.pipe(
     // withLatestFrom(this.cities),
      debounceTime(100),
      map((term) => {
        console.log(term);
        return this._filter(term);
      })
    );
  }

  private _filter(term): City[] {
    const filterValue = term.toLowerCase();
    return this.cities.filter(option =>
      option.name.toLowerCase().includes(filterValue)
    );
  }

  onInstantSearch(form: FormGroup) {
    console.log(form.value);
  }
}

这段代码非常冗长,所以我可能做得很奇怪。

3 个答案:

答案 0 :(得分:8)

fix . (>>=) :: IO a -> IO b

比较forever,即State1

编辑:仅在State2 = State3 = data-fix时有效。如果没有,main = fix (traverse unFix >=>) [ana runService1 initState1, ana runService2 initState2, ana runService3 initState3] 允许:

{{1}}

答案 1 :(得分:4)

我练习,您可能希望将该状态添加到合适的 state monad 中。 StartDate = meetingRequest.Start.ToString(); TimeZone = meetingRequest.TimeZone; var AllTimeZones = TimeZoneInfo.GetSystemTimeZones(); foreach (TimeZoneInfo timeZoneInfo in AllTimeZones) { if (timeZoneInfo.ToString() == TimeZone) { TimeZoneInfo ActualTimeZone = timeZoneInfo; var MeetingWindowStartDate = TimeZoneInfo.ConvertTime( meetingRequest.Start, ActualTimeZone, service.TimeZone); } 库使访问它变得容易:

lens

这样,这并不能使您在原始代码上花很多钱,但是如果您还给{-# LANGUAGE TemplateHaskell #-} import Control.Lens.TH import Control.Monad.Trans.State data AllState = AllState { _s₀ :: State0, _s₁ :: State1, _s₂ :: State2 } makeLenses ''AllState loop :: StateT AllState IO () loop = do s₀ <~ runService0 <$> use s₀ s₁ <~ runService1 <$> use s₁ s₂ <~ runService2 <$> use s₂ loop main = evalStateT loop $ AllState initState0 initState1 initState2 动作指定合适的状态单调类型,它将变得更加方便:

runService

...然后您可以简单地使用zoom机制:

runService0 :: StateT State0 IO ()
runService1 :: StateT State1 IO ()
runService2 :: StateT State2 IO ()

或正如古尔肯格拉斯的建议

loop :: StateT AllState IO ()
loop = do
   zoom s₀ runService0
   zoom s₁ runService1
   zoom s₂ runService2
   loop

答案 2 :(得分:0)

该解决方案不是更简洁,但是解决了原始表述的模糊性:每个过程的“展开”与所有过程的“拉锁在一起”混合在一起。如果我们可以独立定义每个流程,然后在我们认为合适的时候将它们合并,那就太好了。

我们需要以下辅助类型:

newtype Iter = Iter (IO Iter)

unfoldIter :: (s -> IO s) -> s -> Iter
unfoldIter f s = Iter (unfoldIter f <$> f s)

runIter :: Iter -> IO ()
runIter (Iter action) = action >>= runIter

doNothingIter :: Iter
doNothingIter = unfoldIter return ()

zipIter :: Iter -> Iter -> Iter
zipIter (Iter action1) (Iter action2) =
    Iter (zipIter <$> action1 <*> action2)

instance Monoid Iter where
    mempty = doNothingIter
    mappend = zipIter

然后loop变为:

loop :: State1 -> State2 -> State3 -> IO ()
loop s1 s2 s3 = 
    runIter $ unfoldIter runService1 s1
           <> unfoldIter runService2 s2
           <> unfoldIter runService3 s3

如果我们不想定义自己的辅助类型,可以使用提供“压缩”操作的流式库,例如streaming