2011-10-05 27 views
10

Tôi gặp một số bực bội một cái gì đó trong Haskell hôm nay.Lỗi loại kỳ lạ trong biểu thức Haskell cho phép - vấn đề là gì?

Đây là những gì đã xảy ra:

  1. tôi đã viết một hàm trong ghci và cho nó một chữ ký kiểu
  2. ghci phàn nàn về loại
  3. tôi loại bỏ các chữ ký kiểu
  4. ghci chấp nhận chức năng
  5. Tôi đã kiểm tra loại được phỏng đoán
  6. loại được phỏng đoán chính xác giống như loại tôi đã cố gắng cung cấp cho nó
  7. Tôi đã rất đau khổ
  8. tôi phát hiện ra rằng tôi có thể tạo lại vấn đề trong bất kỳ let-biểu
  9. nghiến răng; quyết định tham khảo ý kiến ​​các chuyên gia tại SO

Cố gắng để xác định chức năng với một loại chữ ký:

Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x} :: (MonadPlus m) => (b -> Bool) -> m b -> m b 

<interactive>:1:20: 
    Inferred type is less polymorphic than expected 
     Quantified type variable `b' is mentioned in the environment: 
     m :: (b -> Bool) -> m b -> m b (bound at <interactive>:1:16) 
     f :: (m b -> m b) -> Bool (bound at <interactive>:1:14) 
     Quantified type variable `m' is mentioned in the environment: 
     m :: (b -> Bool) -> m b -> m b (bound at <interactive>:1:16) 
     f :: (m b -> m b) -> Bool (bound at <interactive>:1:14) 
    In the expression: 
      do { x <- m; 
       guard (f x); 
       return x } :: 
      (MonadPlus m) => (b -> Bool) -> m b -> m b 
    In the definition of `myFilterM': 
     myFilterM f m 
        = do { x <- m; 
          guard (f x); 
          return x } :: 
         (MonadPlus m) => (b -> Bool) -> m b -> m b 

Defined chức năng mà không có một loại chữ ký, kiểm tra các loại suy ra:

Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x} 
Prelude Control.Monad> :t myFilterM 
myFilterM :: (MonadPlus m) => (b -> Bool) -> m b -> m b 

sử dụng các chức năng cho tốt tuyệt vời - nó đã làm việc đúng cách:

Prelude Control.Monad> myFilterM (>3) (Just 4) 
Just 4 
Prelude Control.Monad> myFilterM (>3) (Just 3) 
Nothing 

đoán tốt nhất của tôi như những gì đang xảy ra:
loại chú thích bằng cách nào đó không làm việc tốt với let-biểu , khi có một khối.

Đối với điểm thưởng:
có chức năng nào trong bản phân phối Haskell chuẩn thực hiện việc này không? Tôi đã rất ngạc nhiên khi filterM thực hiện điều gì đó rất khác biệt.

+0

Chú thích loại áp dụng cho RHS của định nghĩa, không phải là 'myFilterM', vì vậy bạn nên nói' :: (MonadPlus m) => m b'. Đây là lý do tại sao các loại 'm' và' f' trong thông báo lỗi của bạn rất lạ. Nhưng tôi vẫn nhận được thông báo lỗi "Suy ra loại ít đa hình hơn dự kiến" (mặc dù có nhiều loại hợp lý hơn) và tôi không biết nguyên nhân gây ra điều đó. – dave4420

+0

@ dave4420 Bạn cũng sử dụng GHC 6. *? Họ mã hóa một công cụ suy luận kiểu mới trong GHC 7; có thể đó là một lỗi. – fuz

+0

@FUZxxl Đó là với GHC 6.12.1. Tôi đã thử nó với GHC 7.0.3 và tôi nhận được hai thông báo lỗi thay vì một, không ai trong số họ đề cập đến tính đa hình. Có thể GHC 7 từ chối suy ra các kiểu đối số 'myFilterM'. – dave4420

Trả lời

9

Sự cố là ưu tiên của toán tử loại (::). Bạn đang cố gắng để mô tả các loại myFilterM nhưng những gì bạn đang thực sự làm điều này là:

ghci> let myFilterM f m = (\ 
     do {x <- m; guard (f x); return x} \ 
     :: \ 
     (MonadPlus m) => (b -> Bool) -> m b -> m b)\ 
    ) 

(backslashes chèn vào cho dễ đọc thôi, không legit cú pháp ghci)

Bạn có thấy vấn đề này?Tôi nhận được cùng một vấn đề cho một cái gì đó đơn giản như

ghci> let f x = x + 1 :: (Int -> Int) 
<interactive>:1:15: 
    No instance for (Num (Int -> Int)) 
     arising from the literal `1' 
    Possible fix: add an instance declaration for (Num (Int -> Int)) 
    In the second argument of `(+)', namely `1' 
    In the expression: x + 1 :: Int -> Int 
    In an equation for `f': f x = x + 1 :: Int -> Int 

Giải pháp là để đính kèm chữ ký kiểu để các yếu tố thích hợp:

ghci> let f :: Int -> Int ; f x = x + 1 
ghci> let myFilterM :: (MonadPlus m) => (b -> Bool) -> m b -> m b; myFilterM f m = do {x <- m; guard (f x); return x} 

Và cho điểm thưởng, bạn muốn mfilter (hoogle is your friend).

+0

Cảm ơn bạn! Tôi không thể tin rằng tôi không bao giờ chạy vào điều này trước khi sử dụng ghci. –

1

Tôi không biết những gì loại trình biên dịch bạn sử dụng, nhưng trên nền tảng của tôi (GHC 7.0.3) tôi nhận được một loại không phù hợp đơn giản:

$ ghci 
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help 
Loading package ghc-prim ... linking ... done. 
Loading package integer-gmp ... linking ... done. 
Loading package base ... linking ... done. 
Loading package ffi-1.0 ... linking ... done. 
Prelude> :m +Control.Monad 
Prelude Control.Monad> let myFilterM f m = do {x <- m; guard (f x); return x} :: (MonadPlus m) => (b -> Bool) -> m b -> m b 

<interactive>:1:30: 
    Could not deduce (t1 ~ ((b1 -> Bool) -> m1 b1 -> m1 b1)) 
    from the context (MonadPlus m) 
     bound by the inferred type of 
       myFilterM :: MonadPlus m => t -> t1 -> (b -> Bool) -> m b -> m b 
     at <interactive>:1:5-100 
    or from (MonadPlus m1) 
     bound by an expression type signature: 
       MonadPlus m1 => (b1 -> Bool) -> m1 b1 -> m1 b1 
     at <interactive>:1:21-100 
     `t1' is a rigid type variable bound by 
      the inferred type of 
      myFilterM :: MonadPlus m => t -> t1 -> (b -> Bool) -> m b -> m b 
      at <interactive>:1:5 
    In a stmt of a 'do' expression: x <- m 
    In the expression: 
     do { x <- m; 
      guard (f x); 
      return x } :: 
      MonadPlus m => (b -> Bool) -> m b -> m b 
    In an equation for `myFilterM': 
     myFilterM f m 
      = do { x <- m; 
       guard (f x); 
       return x } :: 
       MonadPlus m => (b -> Bool) -> m b -> m b 

<interactive>:1:40: 
    Could not deduce (t ~ ((m1 b1 -> m1 b1) -> Bool)) 
    from the context (MonadPlus m) 
     bound by the inferred type of 
       myFilterM :: MonadPlus m => t -> t1 -> (b -> Bool) -> m b -> m b 
     at <interactive>:1:5-100 
    or from (MonadPlus m1) 
     bound by an expression type signature: 
       MonadPlus m1 => (b1 -> Bool) -> m1 b1 -> m1 b1 
     at <interactive>:1:21-100 
     `t' is a rigid type variable bound by 
      the inferred type of 
      myFilterM :: MonadPlus m => t -> t1 -> (b -> Bool) -> m b -> m b 
      at <interactive>:1:5 
    The function `f' is applied to one argument, 
    but its type `t' has none 
    In the first argument of `guard', namely `(f x)' 
    In a stmt of a 'do' expression: guard (f x) 
Prelude Control.Monad> 

Tôi đoán các vấn đề nằm trong thực tế, điều đó số :: không đạt đến đối số. Biến thể nhỏ này (lưu ý khai báo loại riêng)

let myFilterM f m = do {x <- m; guard (f x); return x}; myFilterM :: (MonadPlus m) => (b -> Bool) -> m b -> m b 

không có vấn đề gì. Nó có thể liên quan đến trình kiểm tra loại mới trong GHC 7.

3

Đây có thể chỉ là vấn đề về cú pháp chú thích kiểu và ràng buộc ràng buộc. Nếu bạn viết ví dụ của mình là,

let myFilterM :: (MonadPlus m) => (b -> Bool) -> m b -> m b; myFilterM f m = do {x <- m; guard (f x); return x} 

thì GHCi sẽ cung cấp cho bạn 5 người và gửi cho bạn theo cách của bạn.

Các vấn đề liên quan