在函数中使用foldl

时间:2017-05-30 20:26:38

标签: haskell fold type-constraints foldable

我对在Haskell中使用foldl的类型定义有疑问,我有类型:

data Client = GovOrg String
            | Company String Integer Person String
            | Individual Person Bool
            deriving Show

data Person = Person String String Gender
            deriving Show

data Gender = Male | Female | Unknown
  deriving (Show, Eq, Ord)

data GenderStat = GenderStat Gender Integer deriving Show

使用以下函数定义foldl:

clientGender :: Client -> Gender
clientGender client = case client of
                          Company  _ _ (Person _ _ gender) _ -> gender
                          Individual (Person _ _ gender) _   -> gender
                          _                                  -> Unknown

incrementGenderStat :: GenderStat -> GenderStat
incrementGenderStat (GenderStat gender num) = GenderStat gender (num + 1)

genderStats:: [GenderStat] -> Client -> [GenderStat]
genderStats [maleStat, femaleStat, unknownStat] client = case clientGender client of
                                                           Male -> [incrementGenderStat maleStat, femaleStat, unknownStat]
                                                           Female -> [maleStat, incrementGenderStat femaleStat, unknownStat]
                                                           Unknown -> [maleStat, femaleStat, incrementGenderStat unknownStat]

-- genderStatsOfClients :: Client a -> 
genderStatsOfClients = foldl genderStats [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]

当我尝试将模块加载到ghci时,它会抛出错误:

  • Ambiguous type variable ‘t0’ arising from a use of ‘foldl’                                      │
      prevents the constraint ‘(Foldable t0)’ from being solved.                                      │
      Relevant bindings include                                                                       │
        genderStatsOfClients :: t0 Client -> [GenderStat]                                             │
          (bound at src/Section2/DataTypes.hs:82:1)                                                   │
      Probable fix: use a type annotation to specify what ‘t0’ should be.                             │
      These potential instances exist:                                                                │
        instance Foldable (Either a) -- Defined in ‘Data.Foldable’                                    │
        instance Foldable Maybe -- Defined in ‘Data.Foldable’                                         │                                                                
        instance Foldable ((,) a) -- Defined in ‘Data.Foldable’                                       │                                                                
        ...plus one other                                                                             │                                                                
        ...plus 22 instances involving out-of-scope types                                             │                                                                
        (use -fprint-potential-instances to see them all)                                             │                                                                
    • In the expression:                                                                              │
        foldl                                                                                         │
          genderStats                                                                                 │
          [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]                              │
      In an equation for ‘genderStatsOfClients’:                                                      │
          genderStatsOfClients                                                                        │
            = foldl                                                                                   │
                genderStats                                                                           │
                [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]                        │
Failed, modules loaded: none. 

我试图通过为建议的函数提供类型注释来解决这个问题:

-- genderStatsOfClients :: Foldable Client => ([GenderStat] -> a -> [GenderStat]) -> [GenderStat] -> [a] -> [GenderStat]

我想知道如何在这里提供适当的类型约束,如果我使用Foldable Client a,它说它期望Foldable减少一个参数。

我也尝试了类型定义:

genderStatsOfClients :: (Foldable f, Client a) => ([GenderStat] -> (f a) -> [GenderStat]) -> [GenderStat] -> [(f a)] -> [GenderStat]
genderStatsOfClients = foldl genderStats [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]

抛出错误:

src/Section2/DataTypes.hs:81:38: error:                                                               │
    • Expecting one fewer argument to ‘Client’                                                        │
      Expected kind ‘* -> Constraint’, but ‘Client’ has kind ‘*’                                      │
    • In the type signature:                                                                          │
        genderStatsOfClients :: (Foldable f, Client a) =>                                             │
                                ([GenderStat] -> (f a) -> [GenderStat])                               │
                                -> [GenderStat] -> [(f a)] -> [GenderStat]

1 个答案:

答案 0 :(得分:3)

注释你#import "MovieView.h" #import <AudioToolbox/AudioToolbox.h> @implementation MovieView @synthesize selectedCountry, vImagePreview, playit; - (void)viewDidLoad { [super viewDidLoad]; NSDate *today = [NSDate date]; NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"MMM d hh:mm:ss a"]; // display in 12HR/24HR (i.e. 11:25PM or 23:25) format according to User Settings NSString *currentTime = [dateFormatter stringFromDate:today]; self.navigationController.navigationBarHidden = YES; [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault]; [[UIApplication sharedApplication] setStatusBarHidden:NO]; NSError* error4 = nil; AVAudioSession* audioSession = [AVAudioSession sharedInstance]; [audioSession setCategory:AVAudioSessionCategoryAmbient error:&error4]; OSStatus propertySetError = 0; UInt32 allowMixing = true; propertySetError |= AudioSessionSetProperty(kAudioSessionProperty_OtherMixableAudioShouldDuck, sizeof(allowMixing), &allowMixing); // Activate the audio session error4 = nil; if (![audioSession setActive:YES error:&error4]) { NSLog(@"AVAudioSession setActive:YES failed: %@", [error4 localizedDescription]); } //tests // Set audio session category to "play and record" //endtests //this is the end of recording the video and audio NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectoryPath = [paths objectAtIndex:0]; NSString *proud = [[documentsDirectoryPath stringByAppendingPathComponent:@"proud"] stringByAppendingPathComponent:selectedCountry]; NSURL *movieURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"BlueHarvest" ofType:@"mp4"]]; player = [[MPMoviePlayerController alloc] initWithContentURL: movieURL]; player.useApplicationAudioSession=YES; [player prepareToPlay]; player.controlStyle = MPMovieControlStyleNone; player.allowsAirPlay = NO; player.scalingMode = MPMovieScalingModeFill; player.view.frame = self.view.frame; [self.view insertSubview:player.view belowSubview:vImagePreview]; [player setFullscreen:YES animated:YES]; // ... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(movieFinishedCallback:) name:MPMoviePlayerPlaybackDidFinishNotification object:player]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitedFullscreen:) name:MPMoviePlayerDidExitFullscreenNotification object:player]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerWillExitFullscreen:) name:MPMoviePlayerWillExitFullscreenNotification object:player]; [player play]; session = [[AVCaptureSession alloc] init]; [session beginConfiguration]; session.sessionPreset = AVCaptureSessionPresetMedium; CALayer *viewLayer = self.vImagePreview.layer; NSLog(@"viewLayer = %@", viewLayer); self.captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; self.captureVideoPreviewLayer.frame = self.vImagePreview.bounds; [self.captureVideoPreviewLayer setCornerRadius:14]; [self.captureVideoPreviewLayer setBorderWidth:3.0]; [self.captureVideoPreviewLayer setBorderColor:[[UIColor whiteColor] CGColor]]; self.captureVideoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight; [[vImagePreview layer] setCornerRadius:14]; [[vImagePreview layer] setBorderWidth:3.0]; [[vImagePreview layer] setBorderColor:[[UIColor whiteColor] CGColor]]; [self.vImagePreview.layer addSublayer:self.captureVideoPreviewLayer]; AVCaptureDevice *device = [self frontFacingCameraIfAvailable]; NSError *error = nil; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; if (!input) { // Handle the error appropriately. NSLog(@"ERROR: trying to open camera: %@", error); } AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; NSError *error2 = nil; AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error2]; AVCaptureMovieFileOutput *movieFileOutput = [[AVCaptureMovieFileOutput alloc] init]; NSString *archives = [documentsDirectoryPath stringByAppendingPathComponent:@"archives"]; NSString *editedfilename = [[selectedCountry lastPathComponent] stringByDeletingPathExtension]; NSString *datestring = [[editedfilename stringByAppendingString:@" "] stringByAppendingString:currentTime]; NSLog(@"%@", datestring); NSString *outputpathofmovie = [[archives stringByAppendingPathComponent:datestring] stringByAppendingString:@".mp4"]; NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputpathofmovie]; [session addInput:input]; [session addInput:audioInput]; [session addOutput:movieFileOutput]; AVCaptureConnection *videoConnection = nil; for ( AVCaptureConnection *connection in [movieFileOutput connections] ) { NSLog(@"%@", connection); for ( AVCaptureInputPort *port in [connection inputPorts] ) { NSLog(@"%@", port); if ( [[port mediaType] isEqual:AVMediaTypeVideo] ) { videoConnection = connection; } } } if([videoConnection isVideoOrientationSupported]) // **Here it is, its always false** { [videoConnection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight]; } [session commitConfiguration]; [session startRunning]; NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self]; NSLog(@"OutputURL%@", outputURL); } -(void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; switch (orientation) { case UIInterfaceOrientationPortrait: [self.captureVideoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait]; break; case UIInterfaceOrientationPortraitUpsideDown: [self.captureVideoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown]; break; case UIInterfaceOrientationLandscapeLeft: [self.captureVideoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft]; break; case UIInterfaceOrientationLandscapeRight: [self.captureVideoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight]; break; } } - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error { //finished NSLog(@"ErrorMessage%@", error); } -(IBAction)endcall { [player stop]; [session stopRunning]; } -(AVCaptureDevice *)frontFacingCameraIfAvailable { NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; AVCaptureDevice *captureDevice = nil; for (AVCaptureDevice *device in videoDevices) { if (device.position == AVCaptureDevicePositionFront) { captureDevice = device; break; } } // couldn't find one on the front, so just get the default video device. if ( ! captureDevice) { captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; } return captureDevice; } - (void) movieFinishedCallback:(NSNotification*) aNotification { NSLog(@"MovieDone"); [player stop]; [player.view removeFromSuperview]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:player]; [session stopRunning]; [self.navigationController popToRootViewControllerAnimated:NO]; } - (void) exitedFullscreen:(NSNotification*) aNotification { NSLog(@"MovieDone"); [player.view removeFromSuperview]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerDidExitFullscreenNotification object:player]; } - (void)moviePlayerWillExitFullscreen:(NSNotification*) aNotification { [player stop]; [session stopRunning]; [self dismissMoviePlayerViewControllerAnimated]; [[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerWillExitFullscreenNotification object:player]; } @end 的定义,告诉编译器你的可折叠是一个列表:

genderStatsOfClients
相关问题