2013-08-14 25 views
32

Vì các ngữ cảnh và trường hợp linh hoạt này không có sẵn trong tiêu chuẩn Haskell, tôi cho rằng có những vấn đề tiềm năng khi sử dụng chúng. Họ là ai? Họ có thể dẫn đến một số sự mơ hồ, không thể xác định, các trường hợp chồng chéo, v.v. không?Những cạm bẫy khi sử dụng FlexibleContexts và FlexibleInstances là gì?

Có một số similar question chỉ hỏi về FlexibleInstances, chứ không phải FlexibleContexts, nhưng câu trả lời chỉ cho biết "an toàn để sử dụng chúng".

+4

Theo như tôi đã thu thập, họ chỉ là những điều họ không nghĩ đến khi họ viết tiêu chuẩn, nhưng chúng trở nên hữu ích để GHC bao gồm chúng như là phần mở rộng. Rõ ràng là tôi có thể nghĩ rằng mã được viết bằng cách sử dụng chúng sẽ không hoạt động với các trình biên dịch khác. Nhưng tôi chắc rằng người khác biết nhiều hơn. – kqr

+0

bạn có thể xem ví dụ trong [edit history] của [answer] (http://stackoverflow.com/a/15770150/849891) (http://stackoverflow.com/posts/15770150/revisions). Tôi [đầu tiên đã làm điều gì đó sai] (http://stackoverflow.com/revisions/95690635-a708-4c29-a22d-95b23038258d/view-source) (trong vòng 1) và được GHCi đề nghị thêm FlexibleContexts. Và nó được biên dịch. (Ban đầu tôi không có ràng buộc Genome trong lớp, và w/FlexContxs nó được biên dịch). –

+0

@WillNess Điều này rất khó để khám phá, bạn có lẽ sẽ đưa ra một câu trả lời dựa trên nó? –

Trả lời

16

Tôi từng gặp phải những điều sau đây. Answering this question, đầu tiên tôi thử mã này:

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FunctionalDependencies #-} 

class (Eq a, Show a) => Genome a where 
    crossover  :: (Fractional b) => b -> a -> a -> IO (a, a) 
    mutate   :: (Fractional b) => b -> a -> IO a 
    develop   :: (Phenotype b a) => a -> b 

class (Eq a, Show a) => Phenotype a b | a -> b where 
    -- In case of Coevolution where each phenotype needs to be compared to 
    -- every other in the population 
    fitness   :: [a] -> a -> Int 
    genome   :: (Genome b) => a -> b -- here, the problem 

breed parents cross mute = do 
    children <- mapM (\ (dad, mom) -> crossover cross (genome dad) (genome mom)) 
        parents 
    let ch1 = map fst children ++ map snd children 
    mutated <- mapM (mutate mute) ch1 
    return $ map develop mutated 

Và có một lỗi biên dịch và một gợi ý bởi GHCi để thêm tùy chọn FlexibleContexts. Khi tôi đã làm, nó biên dịch OK. Nhưng điều này thực sự không phải là điều đúng đắn, vì tuyên bố ràng buộc đã giới thiệu phạm vi mới cho các biến kiểu, và b trong chữ ký kiểu genome trở nên hoàn toàn không liên quan đến chữ ký trong lớp loại; chưa FlexibleContexts đã cung cấp trang bìa cho việc này.

Với các hạn chế định đúng ở cấp lớp loại,

class (Eq a, Show a, Genome b) => Phenotype a b | a -> b where 
    -- In case of Coevolution where each phenotype needs to be compared to 
    -- every other in the population 
    fitness   :: [a] -> a -> Int 
    genome   :: a -> b 

nó thông qua biên soạn mà không đòi hỏi tùy chọn FlexibleContexts.

+3

Không phải là vấn đề bằng cách khai báo 'genome :: (Genome b) => a -> b' với ràng buộc lớp kiểu, nó thực sự đã giới thiệu một biến kiểu mới' b' làm bóng biến gốc? –

+0

@ PetrPudlák để tuyên bố ràng buộc giới thiệu phạm vi mới cho các biến kiểu? Trong trường hợp đó, phương pháp bộ gen * có thể * trả về một kiểu Genome hoàn toàn không liên quan đến kiểu Phenotype mà nó thuộc về. Điều này chắc chắn sẽ là một dòng chảy thiết kế, và FlexibleInstances sẽ cung cấp một trang bìa cho nó, phải không? Điều đó thực sự sẽ đủ điều kiện cho một pitfall sau đó. :) –

+1

Quá xấu '-Wall' không cảnh báo ở đây. (Tôi không nghĩ rằng đây là một lỗi ... chỉ cần tên bóng. Điều đó nói rằng, mã có một lỗi do điều này.) –

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