2015-03-26 25 views
5

Tôi có một ví dụ về hàm, trong đó tôi không thể viết một loại trong mệnh đề where. replace là một hàm, thay thế tất cả X bằng Y trong một danh sách đã cho.Haskell: Khai báo kiểu trong `where`

replace :: (Eq a) => a -> a -> [a] -> [a] 
replace x y xs = map helper xs 
    where 
    helper :: (Eq a) => a -> a 
    helper = (\el -> if el == x then y else el) 

Khi tôi cố gắng biên dịch chức năng này, tôi nhận được một lỗi:

ProblemsArithmetics.hs:156:31: 
Could not deduce (a ~ a1) 
from the context (Eq a) 
    bound by the type signature for 
      replace :: Eq a => a -> a -> [a] -> [a] 
    at ProblemsArithmetics.hs:152:12-41 
or from (Eq a1) 
    bound by the type signature for helper :: Eq a1 => a1 -> a1 
    at ProblemsArithmetics.hs:155:15-30 
    ‘a’ is a rigid type variable bound by 
     the type signature for replace :: Eq a => a -> a -> [a] -> [a] 
     at ProblemsArithmetics.hs:152:12 
    ‘a1’ is a rigid type variable bound by 
     the type signature for helper :: Eq a1 => a1 -> a1 
     at ProblemsArithmetics.hs:155:15 
Relevant bindings include 
    el :: a1 (bound at ProblemsArithmetics.hs:156:16) 
    helper :: a1 -> a1 (bound at ProblemsArithmetics.hs:156:5) 
    xs :: [a] (bound at ProblemsArithmetics.hs:153:13) 
    y :: a (bound at ProblemsArithmetics.hs:153:11) 
    x :: a (bound at ProblemsArithmetics.hs:153:9) 
    replace :: a -> a -> [a] -> [a] 
    (bound at ProblemsArithmetics.hs:153:1) 
In the second argument of ‘(==)’, namely ‘x’ 
In the expression: el == x 

Cùng lúc đó, nếu tôi bỏ qua

helper :: (Eq a) => a -> a 

mã được biên dịch tốt.

Trong khi tôi hiểu được logic đằng sau nó (a trong replace khai báo kiểu và a trong helper khai báo kiểu khác nhau a s), và có ít nhất 2 cách giải quyết (bỏ qua khai báo kiểu hay vượt qua xy như tham số cho helper chức năng), câu hỏi của tôi là:

Có cách nào để báo cho trình biên dịch biết rằng tôi có cùng loại trong cả hai loại khai báo không?

+3

Có: https://wiki.haskell.org/Scoped_type_variables – Jubobs

+2

Thử thêm '{- # LANGUAGE ScopedTypeVariables # -}'. Tôi không thể kiểm tra bây giờ, bất cứ ai được tự do để biến bình luận của tôi thành một câu trả lời. – Franky

Trả lời

10

Nếu bạn bật ScopedTypeVariables và giới thiệu biến kiểu với forall, thì nó sẽ hiển thị trong phạm vi bên trong.

{-# LANGUAGE ScopedTypeVariables #-} 

replace :: forall a. (Eq a) => a -> a -> [a] -> [a] 
replace x y xs = map helper xs 
    where 
    helper :: a -> a 
    helper = (\el -> if el == x then y else el) 
Các vấn đề liên quan