-এক্সোএলবিআবিগিউস টাইপগুলি কখন উপযুক্ত?


212

এর সংজ্ঞা সম্পর্কে আমি সিনট্যাকটিক -২.০ সম্পর্কে সম্প্রতি একটি প্রশ্ন পোস্ট করেছি । আমি জিএইচসি 7.6 এ কাজ করেছি :share

{-# LANGUAGE GADTs, TypeOperators, FlexibleContexts #-}

import Data.Syntactic
import Data.Syntactic.Sugar.BindingT

data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

share :: (Let :<: sup,
          sup ~ Domain b, sup ~ Domain a,
          Syntactic a, Syntactic b,
          Syntactic (a -> b),
          SyntacticN (a -> (a -> b) -> b) 
                     fi)
           => a -> (a -> b) -> b
share = sugarSym Let

তবে জিএইচসি 7.8 -XAllowAmbiguousTypesসেই স্বাক্ষরটি সংকলন করতে চায় । বিকল্পভাবে, আমি এর fiসাথে প্রতিস্থাপন করতে পারি

(ASTF sup (Internal a) -> AST sup ((Internal a) :-> Full (Internal b)) -> ASTF sup (Internal b))

যা ফান্ডেপ দ্বারা প্রদত্ত প্রকার SyntacticN। এটি আমাকে এক্সটেনশন এড়াতে দেয়। অবশ্যই এটি হয়

  • ইতিমধ্যে একটি বৃহত স্বাক্ষরে যুক্ত করতে খুব দীর্ঘ টাইপ
  • ম্যানুয়ালি আহরণ ক্লান্তিকর
  • তহবিলের কারণে অপ্রয়োজনীয়

আমার প্রশ্নগুলি হ'ল:

  1. এটি কি গ্রহণযোগ্য ব্যবহার -XAllowAmbiguousTypes?
  2. সাধারণভাবে, কখন এই এক্সটেনশনটি ব্যবহার করা উচিত? একটি উত্তর এখানে পরামর্শ দেয় "এটি প্রায়শই ভাল ধারণা নয়"।
  3. যদিও আমি ডক্সটি পড়েছি, তবে এখনও সীমাবদ্ধতা অস্পষ্ট কিনা তা সিদ্ধান্ত নিতে আমার সমস্যা হচ্ছে। বিশেষত, ডেটা.সাইনট্যাকটিক.সুগার থেকে এই ফাংশনটি বিবেচনা করুন:

    sugarSym :: (sub :<: AST sup, ApplySym sig fi sup, SyntacticN f fi) 
             => sub sig -> f
    sugarSym = sugarN . appSym
    

    আমার কাছে মনে হচ্ছে fi(এবং সম্ভবত sup) এখানে অস্পষ্ট হওয়া উচিত, তবে এটি এক্সটেনশন ছাড়াই সংকলন করে। কেন sugarSymঅস্পষ্ট shareহয়? যেহেতু shareএকটি প্রয়োগ sugarSym, তাই shareসমস্ত বাধা সরাসরি থেকে আসে sugarSym


4
কোন কারণে আপনি শুধু জন্য আমাদের অনুমিত টাইপ ব্যবহার করতে পারবেন না কি sugarSym Let, যা (SyntacticN f (ASTF sup a -> ASTF sup (a -> b) -> ASTF sup b), Let :<: sup) => fএবং দ্ব্যর্থক টাইপ ভেরিয়েবল সঙ্গে যুক্ত নয়?
kosmikus

3
@ Kosmikus Sorrt প্রতিক্রিয়া জানাতে এত দিন লেগেছে। এই কোডটি অনুমিত স্বাক্ষরের সাথে সংকলন করে না share, তবে প্রশ্নটিতে উল্লিখিত স্বাক্ষরগুলির মধ্যে দুটি ব্যবহার করা হলে সংকলন করে । আপনার প্রশ্নটি আগের পোস্টের
ক্রোকিয়া

3
সংজ্ঞায়িত আচরণ সম্ভবত সবচেয়ে উপযুক্ত শব্দ নয়। একটি প্রোগ্রাম ভিত্তিক বন্ধ বুঝতে এটি শক্ত। সমস্যাটি হ্রাসযোগ্যতা এবং জিএইচসিআই আপনার প্রোগ্রামের প্রকারগুলি প্রমাণ করতে সক্ষম হচ্ছে না। একটি দীর্ঘ আলোচনা রয়েছে যা আপনাকে কেবল এই বিষয়ে আগ্রহী। haskell.org/pipermail/haskell-cafe/2008-April/041397.html
BlamKiwi

6
(3) হিসাবে, টাইপটি সিনট্যাকটিকন (যেমন, চ - ফাই) এবং অ্যাপ্লিকেশন (বিশেষত, ফাই -> সিগ, সাপ) এর সংজ্ঞা অনুসারে কার্যকরী নির্ভরশীলতার কারণে অস্পষ্ট নয়। যে থেকে, আপনি যে পেতে fএকা যথেষ্ট সম্পূর্ণরূপে দুর্বোধ্য sig, fiএবং sup
ব্যবহারকারী 2141650

3
@ ব্যবহারকারী2141650 দুঃখিত, উত্তর দিতে এত দিন লেগেছে। আপনি fundep বলছে SyntacticNতোলে fiমধ্যে দ্ব্যর্থহীন sugarSym, কিন্তু তারপর কেন সত্য একই নয় fiমধ্যে share?
ক্রোকিয়া

উত্তর:


12

আমি সিনট্যাক্টিকের কোনও প্রকাশিত সংস্করণ দেখতে পাচ্ছি না যার স্বাক্ষরগুলি sugarSymসেই সঠিক টাইপের নাম ব্যবহার করে , তাই আমি প্রতিশ্রুতি 8cfd02 at এর বিকাশ শাখাটি ব্যবহার করব , এটি সর্বশেষ সংস্করণ যা এখনও এই নামগুলি ব্যবহার করে।

সুতরাং, জিএইচসি fiআপনার ধরণের স্বাক্ষরটি সম্পর্কে অভিযোগ করে তবে এটির জন্য কেন নয় sugarSym? আপনি যে ডকুমেন্টেশনের সাথে লিঙ্ক করেছেন সেটি ব্যাখ্যা করে যে কোনও প্রকার দ্বিধাটির ডানদিকে উপস্থিত না হলে অস্পষ্ট, যদি না সীমাবদ্ধতা অন্যান্য অ-দ্বিধাগ্রস্ত প্রকারের থেকে অন্যথায়-দ্ব্যর্থক প্রকারটি নির্ধারণ করতে কার্যকরী নির্ভরতা ব্যবহার করে না। সুতরাং আসুন দুটি ফাংশনের প্রসঙ্গটি তুলনা করি এবং কার্যকরী নির্ভরতাগুলি সন্ধান করি।

class ApplySym sig f sym | sig sym -> f, f -> sig sym
class SyntacticN f internal | f -> internal

sugarSym :: ( sub :<: AST sup
            , ApplySym sig fi sup
            , SyntacticN f fi
            ) 
         => sub sig -> f

share :: ( Let :<: sup
         , sup ~ Domain b
         , sup ~ Domain a
         , Syntactic a
         , Syntactic b
         , Syntactic (a -> b)
         , SyntacticN (a -> (a -> b) -> b) fi
         )
      => a -> (a -> b) -> b

সুতরাং জন্য sugarSym, অ-দ্ব্যর্থক ধরনের হয় sub, sigএবং f, এবং যারা থেকে আমরা অর্ডার সব অন্যান্য, প্রেক্ষাপটে ব্যবহৃত যথা ধরনের দুর্বোধ্য করার জন্য কার্মিক নির্ভরতা অনুসরণ করতে সক্ষম হওয়া উচিত supএবং fi। এবং প্রকৃতপক্ষে, f -> internalকার্যকরী নির্ভরতা SyntacticNআমাদের আমাদের fনিরস্ত করতে ব্যবহার করে fiএবং এরপরে f -> sig symকার্যকরী নির্ভরতা ApplySymআমাদের সদ্য-বিভ্রান্তিকরকে নিরস্ত fiকরতে ব্যবহার করে sup(এবং sigযা ইতিমধ্যে দ্ব্যর্থহীন ছিল)। সুতরাং যে ব্যাখ্যা দিয়েছে কেন sugarSymপ্রয়োজন হয় না AllowAmbiguousTypesএক্সটেনশান।

আসুন এখন তাকান sugar। প্রথম যে বিষয়টি আমি লক্ষ্য করছি তা হল যে সংকলকটি একটি অস্পষ্ট ধরণের সম্পর্কে অভিযোগ করছে না , বরং ওভারল্যাপিংয়ের উদাহরণগুলি সম্পর্কে:

Overlapping instances for SyntacticN b fi
  arising from the ambiguity check for share
Matching givens (or their superclasses):
  (SyntacticN (a -> (a -> b) -> b) fi1)
Matching instances:
  instance [overlap ok] (Syntactic f, Domain f ~ sym,
                         fi ~ AST sym (Full (Internal f))) =>
                        SyntacticN f fi
    -- Defined in ‘Data.Syntactic.Sugar’
  instance [overlap ok] (Syntactic a, Domain a ~ sym,
                         ia ~ Internal a, SyntacticN f fi) =>
                        SyntacticN (a -> f) (AST sym (Full ia) -> fi)
    -- Defined in ‘Data.Syntactic.Sugar’
(The choice depends on the instantiation of b, fi’)
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes

সুতরাং আমি যদি এই অধিকারটি পড়ছি তবে এটি এমন নয় যে জিএইচসি আপনার প্রকারগুলি দ্বিধাগ্রস্থ বলে মনে করে, বরং এটি আপনার ধরণের দ্বিধাহীন কিনা তা যাচাই করার সময়, জিএইচসি একটি পৃথক, পৃথক সমস্যার মুখোমুখি হয়েছিল। এটি তখন আপনাকে বলছে যে আপনি যদি GHC কে অস্পষ্টতা পরীক্ষা না করতে বলে থাকেন, তবে এটি পৃথক সমস্যাটির মুখোমুখি হত না। এটি ব্যাখ্যা করে যে অ্যাম্বিগিউস টাইপগুলি মঞ্জুরি দেওয়ার কারণে আপনার কোডটি সংকলনের অনুমতি দেয়।

তবে ওভারল্যাপিং দৃষ্টান্তগুলির সাথে সমস্যাটি রয়ে গেছে। জিএইচসি দ্বারা তালিকাভুক্ত দুটি উদাহরণ ( SyntacticN f fiএবং SyntacticN (a -> f) ...) একে অপরের সাথে ওভারল্যাপ করে। আশ্চর্যজনকভাবে যথেষ্ট, এটির মধ্যে প্রথমটি অন্য কোনও উদাহরণের সাথে ওভারল্যাপ হওয়া উচিত বলে মনে হচ্ছে এটি সন্দেহজনক। এবং [overlap ok]মানে কি?

আমি সন্দেহ করি যে সিন্ট্যাকটিক ওভারল্যাপিংআইজনেসগুলি সংকলিত। এবং কোড খুঁজছেন , প্রকৃতপক্ষে এটি।

কিছুটা পরীক্ষা-নিরীক্ষা করে মনে হয় যে, একজনের তুলনায় অন্যটির চেয়ে কঠোরভাবে জেনারেল স্পষ্ট হয়ে উঠেছে যে জিএইচসি ওভারল্যাপিংয়ের উদাহরণগুলির সাথে ঠিক আছে:

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Foo a where
  whichOne :: a -> String

instance Foo a where
  whichOne _ = "a"

instance Foo [a] where
  whichOne _ = "[a]"

-- |
-- >>> main
-- [a]
main :: IO ()
main = putStrLn $ whichOne (undefined :: [Int])

অন্য কোনওটির তুলনায় স্পষ্টতই কোনও ভাল ফিট না হলে ওভারল্যাপিংয়ের উদাহরণগুলির সাথে জিএইচসি ঠিক নেই:

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Foo a where
  whichOne :: a -> String

instance Foo (f Int) where  -- this is the line which changed
  whichOne _ = "f Int"

instance Foo [a] where
  whichOne _ = "[a]"

-- |
-- >>> main
-- Error: Overlapping instances for Foo [Int]
main :: IO ()
main = putStrLn $ whichOne (undefined :: [Int])

আপনার ধরণের স্বাক্ষর ব্যবহার করে SyntacticN (a -> (a -> b) -> b) fiএবং অন্যগুলির চেয়ে ভালও নয় SyntacticN f finor SyntacticN (a -> f) (AST sym (Full ia) -> fi)আমি যদি আপনার ধরণের স্বাক্ষরের সেই অংশটি SyntacticN a fiবা SyntacticN (a -> (a -> b) -> b) (AST sym (Full ia) -> fi)এটিতে পরিবর্তন করি তবে জিএইচসি আর ওভারল্যাপ সম্পর্কে আর অভিযোগ করে না।

আমি যদি আপনি হয়ে থাকি তবে আমি সেই দুটি সম্ভাব্য দৃষ্টান্তের সংজ্ঞাটি দেখব এবং নির্ধারণ করবো যে এই দুটি বাস্তবায়নগুলির মধ্যে একটি আপনার পছন্দসই কিনা।


2

আমি এটি AllowAmbiguousTypesব্যবহারের জন্য খুব সুবিধাজনক আবিষ্কার করেছি TypeApplicationsGHC.TypeLitsnatVal :: forall n proxy . KnownNat n => proxy n -> Integer থেকে ফাংশনটি বিবেচনা করুন ।

এই ফাংশনটি ব্যবহার করতে, আমি লিখতে পারি natVal (Proxy::Proxy5)। একটি বিকল্প শৈলী ব্যবহার করা TypeApplications: natVal @5 Proxy। ধরণ Proxyধরণ অ্যাপ্লিকেশন দ্বারা অনুমিত হয়, এবং এটা প্রত্যেক সময় আপনি কল লিখতে আছে বিরক্তিকর natVal। এইভাবে আমরা সক্ষম AmbiguousTypesএবং লিখতে পারি:

{-# Language AllowAmbiguousTypes, ScopedTypeVariables, TypeApplications #-}

ambiguousNatVal :: forall n . (KnownNat n) => Integer
ambiguousNatVal = natVal @n Proxy

five = ambiguousNatVal @5 -- no `Proxy ` needed!

তবে খেয়াল করুন যে একবার আপনি দ্ব্যর্থহীন হয়ে গেলে আপনি আর ফিরে যেতে পারবেন না !

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.